From 982f409cecd73c70a0a7c5e6559696776b6c6dd5 Mon Sep 17 00:00:00 2001 From: Svante Signell Date: Sun, 12 May 2013 12:22:20 +0100 Subject: Add support for the GNU/Hurd architecture [As with GNU/kFreeBSD, it's treated as "Linux": all three use the GNU libc and runtime linker, which is mostly what matters for ioquake3. -smcv] Bug-Debian: http://bugs.debian.org/679330 Reviewed-by: Simon McVittie --- Makefile | 2 +- src/qcommon/q_platform.h | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index eff1a6b1..45676882 100644 --- a/Makefile +++ b/Makefile @@ -305,7 +305,7 @@ MKDIR=mkdir EXTRA_FILES= CLIENT_EXTRA_FILES= -ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu")) +ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) ifeq ($(ARCH),x86_64) LIB=lib64 diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h index 39d1672c..f04bf433 100644 --- a/src/qcommon/q_platform.h +++ b/src/qcommon/q_platform.h @@ -170,14 +170,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //================================================================= LINUX === -#if defined(__linux__) || defined(__FreeBSD_kernel__) +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) #include #if defined(__linux__) #define OS_STRING "linux" -#else +#elif defined(__FreeBSD_kernel__) #define OS_STRING "kFreeBSD" +#else +#define OS_STRING "GNU" #endif #define ID_INLINE inline -- cgit From f1a51e13c659ac80ccc2e9bc453d7e671262d564 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Fri, 18 Jul 2014 00:15:05 +0200 Subject: sayto cmd with player name completion --- src/client/cl_main.c | 98 ++++++++++++++++++++++++++++ src/qcommon/common.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/qcommon/qcommon.h | 5 ++ src/server/sv_ccmds.c | 65 +++++++++++++++++++ 4 files changed, 342 insertions(+) diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 03bd542c..5b3f6028 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -1731,6 +1731,50 @@ static void CL_CompleteRcon( char *args, int argNum ) } } +/* +================== +CL_CompletePlayerName +================== +*/ +static void CL_CompletePlayerName( char *args, int argNum ) +{ + if( argNum == 2 ) + { + char names[MAX_CLIENTS][MAX_NAME_LENGTH]; + char *namesPtr[MAX_CLIENTS]; + int i; + int clientCount; + int nameCount; + const char *info; + const char *name; + + //configstring + info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO]; + clientCount = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); + + nameCount = 0; + + for( i = 0; i < clientCount; i++ ) { + if( i == clc.clientNum ) + continue; + + info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_PLAYERS+i]; + + name = Info_ValueForKey( info, "n" ); + if( name[0] == '\0' ) + continue; + Q_strncpyz( names[nameCount], name, sizeof(names[nameCount]) ); + Q_CleanStr( names[nameCount] ); + + namesPtr[nameCount] = names[nameCount]; + nameCount++; + } + qsort( (void*)namesPtr, nameCount, sizeof( namesPtr[0] ), Com_strCompare ); + + Field_CompletePlayerName( namesPtr, nameCount ); + } +} + /* ===================== CL_Rcon_f @@ -3474,6 +3518,56 @@ static void CL_GenerateQKey(void) } } +void CL_Sayto_f( void ) { + char *rawname; + char name[MAX_NAME_LENGTH]; + char cleanName[MAX_NAME_LENGTH]; + const char *info; + int count; + int i; + int clientNum; + char *p; + + if ( Cmd_Argc() < 3 ) { + Com_Printf ("sayto \n"); + return; + } + + rawname = Cmd_Argv(1); + + Com_FieldStringToPlayerName( name, MAX_NAME_LENGTH, rawname ); + + info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO]; + count = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); + + clientNum = -1; + for( i = 0; i < count; i++ ) { + + info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_PLAYERS+i]; + Q_strncpyz( cleanName, Info_ValueForKey( info, "n" ), sizeof(cleanName) ); + Q_CleanStr( cleanName ); + + if ( !Q_stricmp( cleanName, name ) ) { + clientNum = i; + break; + } + } + if( clientNum <= -1 ) + { + Com_Printf ("No such player name: %s.\n", name); + return; + } + + p = Cmd_ArgsFrom(2); + + if ( *p == '"' ) { + p++; + p[strlen(p)-1] = 0; + } + + CL_AddReliableCommand(va("tell %i \"%s\"", clientNum, p ), qfalse); +} + /* ==================== CL_Init @@ -3663,6 +3757,10 @@ void CL_Init( void ) { Cmd_AddCommand ("model", CL_SetModel_f ); Cmd_AddCommand ("video", CL_Video_f ); Cmd_AddCommand ("stopvideo", CL_StopVideo_f ); + if( !com_dedicated->integer ) { + Cmd_AddCommand ("sayto", CL_Sayto_f ); + Cmd_SetCommandCompletionFunc( "sayto", CL_CompletePlayerName ); + } CL_InitRef(); SCR_Init (); diff --git a/src/qcommon/common.c b/src/qcommon/common.c index fef14331..11e723c1 100644 --- a/src/qcommon/common.c +++ b/src/qcommon/common.c @@ -3421,3 +3421,177 @@ qboolean Com_IsVoipTarget(uint8_t *voipTargets, int voipTargetsSize, int clientN return qfalse; } + +/* +=============== +Field_CompletePlayerName +=============== +*/ +static qboolean Field_CompletePlayerNameFinal( qboolean whitespace ) +{ + int completionOffset; + + if( matchCount == 0 ) + return qtrue; + + completionOffset = strlen( completionField->buffer ) - strlen( completionString ); + + Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch, + sizeof( completionField->buffer ) - completionOffset ); + + completionField->cursor = strlen( completionField->buffer ); + + if( matchCount == 1 && whitespace ) + { + Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " ); + completionField->cursor++; + return qtrue; + } + + return qfalse; +} + +static void Name_PlayerNameCompletion( const char **names, int nameCount, void(*callback)(const char *s) ) +{ + int i; + + for( i = 0; i < nameCount; i++ ) { + callback( names[ i ] ); + } +} + +qboolean Com_FieldStringToPlayerName( char *name, int length, const char *rawname ) +{ + char hex[5]; + int i; + int ch; + + if( name == NULL || rawname == NULL ) + return qfalse; + + if( length <= 0 ) + return qtrue; + + for( i = 0; *rawname && i + 1 <= length; rawname++, i++ ) { + if( *rawname == '\\' ) { + Q_strncpyz( hex, rawname + 1, sizeof(hex) ); + ch = Com_HexStrToInt( hex ); + if( ch > -1 ) { + name[i] = ch; + rawname += 4; //hex string length, 0xXX + } else { + name[i] = *rawname; + } + } else { + name[i] = *rawname; + } + } + name[i] = '\0'; + + return qtrue; +} + +qboolean Com_PlayerNameToFieldString( char *str, int length, const char *name ) +{ + const char *p; + int i; + int x1, x2; + + if( str == NULL || name == NULL ) + return qfalse; + + if( length <= 0 ) + return qtrue; + + *str = '\0'; + p = name; + + for( i = 0; *p != '\0'; i++, p++ ) + { + if( i + 1 >= length ) + break; + + if( *p <= ' ' ) + { + if( i + 5 + 1 >= length ) + break; + + x1 = *p >> 4; + x2 = *p & 15; + + str[i+0] = '\\'; + str[i+1] = '0'; + str[i+2] = 'x'; + str[i+3] = x1 > 9 ? x1 - 10 + 'a' : x1 + '0'; + str[i+4] = x2 > 9 ? x2 - 10 + 'a' : x2 + '0'; + + i += 4; + } else { + str[i] = *p; + } + } + str[i] = '\0'; + + return qtrue; +} + +void Field_CompletePlayerName( char **names, int nameCount ) +{ + qboolean whitespace; + + matchCount = 0; + shortestMatch[ 0 ] = 0; + + if( nameCount <= 0 ) + return; + + Name_PlayerNameCompletion( names, nameCount, FindMatches ); + + if( completionString[0] == '\0' ) + { + Com_PlayerNameToFieldString( shortestMatch, sizeof( shortestMatch ), names[ 0 ] ); + } + + //allow to tab player names + //if full player name switch to next player name + if( completionString[0] != '\0' + && Q_stricmp( shortestMatch, completionString ) == 0 + && nameCount > 1 ) + { + int i; + + for( i = 0; i < nameCount; i++ ) { + if( Q_stricmp( names[ i ], completionString ) == 0 ) + { + i++; + if( i >= nameCount ) + { + i = 0; + } + + Com_PlayerNameToFieldString( shortestMatch, sizeof( shortestMatch ), names[ i ] ); + break; + } + } + } + + if( matchCount > 1 ) + { + Com_Printf( "]%s\n", completionField->buffer ); + + Name_PlayerNameCompletion( names, nameCount, PrintMatches ); + } + + whitespace = nameCount == 1? qtrue: qfalse; + if( !Field_CompletePlayerNameFinal( whitespace ) ) + { + + } +} + +int QDECL Com_strCompare( const void *a, const void *b ) +{ + const char **pa = (const char **)a; + const char **pb = (const char **)b; + return strcmp( *pa, *pb ); +} diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index 98d1f1ec..d71531b6 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -740,6 +740,7 @@ void Field_CompleteFilename( const char *dir, const char *ext, qboolean stripExt, qboolean allowNonPureFilesOnDisk ); void Field_CompleteCommand( char *cmd, qboolean doCommands, qboolean doCvars ); +void Field_CompletePlayerName( char **names, int count ); /* ============================================================== @@ -815,6 +816,10 @@ void Com_StartupVariable( const char *match ); // if match is NULL, all set commands will be executed, otherwise // only a set with the exact name. Only used during startup. +qboolean Com_PlayerNameToFieldString( char *str, int length, const char *name ); +qboolean Com_FieldStringToPlayerName( char *name, int length, const char *rawname ); +int QDECL Com_strCompare( const void *a, const void *b ); + extern cvar_t *com_developer; extern cvar_t *com_dedicated; diff --git a/src/server/sv_ccmds.c b/src/server/sv_ccmds.c index 3ec3b8c7..1cc6cf3e 100644 --- a/src/server/sv_ccmds.c +++ b/src/server/sv_ccmds.c @@ -223,6 +223,71 @@ static void SV_MapRestart_f( void ) { } +/* +================== +SV_ConSayto_f +================== +*/ +static void SV_ConSayto_f(void) { + char *p; + char text[1024]; + client_t *cl; + char *rawname; + char name[MAX_NAME_LENGTH]; + char cleanName[MAX_NAME_LENGTH]; + client_t *saytocl; + int i; + + // make sure server is running + if ( !com_sv_running->integer ) { + Com_Printf( "Server is not running.\n" ); + return; + } + + if ( Cmd_Argc() < 3 ) { + Com_Printf ("Usage: sayto \n"); + return; + } + + rawname = Cmd_Argv(1); + + //allowing special characters in the console + //with hex strings for player names + Com_FieldStringToPlayerName( name, MAX_NAME_LENGTH, rawname ); + + saytocl = NULL; + for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { + if ( !cl->state ) { + continue; + } + Q_strncpyz( cleanName, cl->name, sizeof(cleanName) ); + Q_CleanStr( cleanName ); + + if ( !Q_stricmp( cleanName, name ) ) { + saytocl = cl; + break; + } + } + if( !saytocl ) + { + Com_Printf ("No such player name: %s.\n", name); + return; + } + + strcpy (text, "console_sayto: "); + p = Cmd_ArgsFrom(2); + + if ( *p == '"' ) { + p++; + p[strlen(p)-1] = 0; + } + + strcat(text, p); + + SV_SendServerCommand(saytocl, "chat \"%s\"", text); +} + + /* ================== SV_Heartbeat_f -- cgit From 05d3587f154a7ef4ad9af6457ba48734f94319b8 Mon Sep 17 00:00:00 2001 From: Brenton Bostick Date: Fri, 3 Oct 2014 21:59:26 -0400 Subject: Add mingw prefix for cygwin32 and mingw32 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 45676882..105fff05 100644 --- a/Makefile +++ b/Makefile @@ -507,7 +507,7 @@ ifeq ($(PLATFORM),mingw32) MINGW_PREFIXES=amd64-mingw32msvc x86_64-w64-mingw32 endif ifeq ($(ARCH),x86) - MINGW_PREFIXES=i586-mingw32msvc i686-w64-mingw32 + MINGW_PREFIXES=i586-mingw32msvc i686-w64-mingw32 i686-pc-mingw32 endif ifndef CC -- cgit From 61f647351e041042a905153f3f9e8131b3193403 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Oct 2014 17:10:41 +0100 Subject: qcurl_multi_add_handle error check --- src/client/cl_curl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 8d083877..c3d0c7c8 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -212,6 +212,8 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { + CURLMcode result; + clc.cURLUsed = qtrue; Com_Printf("URL: %s\n", remoteURL); Com_DPrintf("***** CL_cURL_BeginDownload *****\n" @@ -272,7 +274,11 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) "failed"); return; } - qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); + result = qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); + if(result != CURLM_OK) { + Com_Error(ERR_DROP,"CL_cURL_BeginDownload: qcurl_multi_add_handle() failed: %s", qcurl_multi_strerror(result)); + return; + } if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) && !clc.cURLDisconnected) { -- cgit From 490d0b226e6a08433a12b356cc1460e0a50019b1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 1 Oct 2014 09:35:49 +0100 Subject: Don't crash if more than 128 modes are available --- src/sdl/sdl_glimp.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index 51b448a2..1f45551f 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -135,7 +135,8 @@ static void GLimp_DetectAvailableModes(void) { int i, j; char buf[ MAX_STRING_CHARS ] = { 0 }; - SDL_Rect modes[ 128 ]; + size_t numSDLModes; + SDL_Rect *modes; int numModes = 0; int display = SDL_GetWindowDisplayIndex( SDL_window ); @@ -147,7 +148,14 @@ static void GLimp_DetectAvailableModes(void) return; } - for( i = 0; i < SDL_GetNumDisplayModes( display ); i++ ) + numSDLModes = SDL_GetNumDisplayModes( display ); + modes = SDL_calloc( numSDLModes, sizeof( SDL_Rect )); + if ( !modes ) + { + ri.Error( ERR_FATAL, "Out of memory\n" ); + } + + for( i = 0; i < numSDLModes; i++ ) { SDL_DisplayMode mode; @@ -157,6 +165,7 @@ static void GLimp_DetectAvailableModes(void) if( !mode.w || !mode.h ) { ri.Printf( PRINT_ALL, "Display supports any resolution\n" ); + SDL_free( modes ); return; } @@ -198,6 +207,7 @@ static void GLimp_DetectAvailableModes(void) ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf ); ri.Cvar_Set( "r_availableModes", buf ); } + SDL_free( modes ); } #define R_FAILSAFE_WIDTH 640 -- cgit From 5bb6bcb0052aab3357d4b69d5d77b05d3f6b8f20 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sat, 17 Jan 2015 18:15:03 +0100 Subject: No unix memmove for msvc --- src/tools/lcc/cpp/unix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/lcc/cpp/unix.c b/src/tools/lcc/cpp/unix.c index 3e70b562..75e5b6d3 100644 --- a/src/tools/lcc/cpp/unix.c +++ b/src/tools/lcc/cpp/unix.c @@ -105,7 +105,8 @@ char *basepath( char *fname ) /* memmove is defined here because some vendors don't provide it at all and others do a terrible job (like calling malloc) */ // -- ouch, that hurts -- ln -#ifndef MACOS_X /* always use the system memmove() on Mac OS X. --ryan. */ +/* always use the system memmove() on Mac OS X. --ryan. */ +#if !defined(MACOS_X) && !defined(_MSC_VER) #ifdef memmove #undef memmove #endif -- cgit From 6038fb1f0507accee76005883ebb3776931c5b59 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 18 Jan 2015 18:41:06 +0100 Subject: SIGABRT is in ANSI and POSIX.1, and SIGIOT isn't. --- src/sys/sys_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c index 4e6b1ebf..dd77e0da 100644 --- a/src/sys/sys_unix.c +++ b/src/sys/sys_unix.c @@ -806,7 +806,7 @@ void Sys_PlatformInit( void ) signal( SIGHUP, Sys_SigHandler ); signal( SIGQUIT, Sys_SigHandler ); signal( SIGTRAP, Sys_SigHandler ); - signal( SIGIOT, Sys_SigHandler ); + signal( SIGABRT, Sys_SigHandler ); signal( SIGBUS, Sys_SigHandler ); Sys_SetFloatEnv(); -- cgit From a6e2daaf0a8b670df9f5ea7daf1d88c60ccf5c1a Mon Sep 17 00:00:00 2001 From: ZsoltM Date: Fri, 30 Jan 2015 22:52:53 +0100 Subject: added mingw64 (msys2) platform support --- Makefile | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 105fff05..c634adae 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,13 @@ PLATFORM=$(COMPILE_PLATFORM) endif export PLATFORM +ifeq ($(PLATFORM),mingw32) + MINGW=1 +endif +ifeq ($(PLATFORM),mingw64) + MINGW=1 +endif + ifeq ($(COMPILE_ARCH),i86pc) COMPILE_ARCH=x86 endif @@ -150,7 +157,7 @@ USE_CURL=1 endif ifndef USE_CURL_DLOPEN - ifeq ($(PLATFORM),mingw32) + ifdef MINGW USE_CURL_DLOPEN=0 else USE_CURL_DLOPEN=1 @@ -493,7 +500,7 @@ else # ifeq darwin # SETUP AND BUILD -- MINGW32 ############################################################################# -ifeq ($(PLATFORM),mingw32) +ifdef MINGW ifeq ($(CROSS_COMPILING),1) # If CC is already set to something generic, we probably want to use @@ -639,7 +646,7 @@ ifeq ($(PLATFORM),mingw32) SDLDLL=SDL2.dll endif -else # ifeq mingw32 +else # ifdef MINGW ############################################################################# # SETUP AND BUILD -- FREEBSD @@ -890,7 +897,7 @@ else # ifeq sunos endif #Linux endif #darwin -endif #mingw32 +endif #MINGW endif #FreeBSD endif #OpenBSD endif #NetBSD @@ -1536,7 +1543,7 @@ Q3OBJ = \ $(B)/client/con_log.o \ $(B)/client/sys_main.o -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3OBJ += \ $(B)/client/con_passive.o else @@ -1980,7 +1987,7 @@ ifeq ($(HAVE_VM_COMPILED),true) endif endif -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3OBJ += \ $(B)/client/win_resource.o \ $(B)/client/sys_win32.o @@ -2119,7 +2126,7 @@ ifeq ($(HAVE_VM_COMPILED),true) endif endif -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3DOBJ += \ $(B)/ded/win_resource.o \ $(B)/ded/sys_win32.o \ -- cgit From fb3b786df5159b7a2a67dda8c51cd48a78801d50 Mon Sep 17 00:00:00 2001 From: Jeff Kent Date: Fri, 20 Mar 2015 19:24:07 -0500 Subject: fix buffer overflow in CL_CheckForResend --- src/client/cl_main.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 5b3f6028..77df2e01 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -2356,9 +2356,9 @@ Resend a connect message if the last one has timed out ================= */ void CL_CheckForResend( void ) { - int port, i; + int port; char info[MAX_INFO_STRING]; - char data[MAX_INFO_STRING]; + char data[MAX_INFO_STRING + 10]; // don't send anything if playing back a demo if ( clc.demoplaying ) { @@ -2399,19 +2399,8 @@ void CL_CheckForResend( void ) { Info_SetValueForKey( info, "qport", va("%i", port ) ); Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) ); - strcpy(data, "connect "); - // TTimo adding " " around the userinfo string to avoid truncated userinfo on the server - // (Com_TokenizeString tokenizes around spaces) - data[8] = '"'; - - for(i=0;i Date: Fri, 12 Jun 2015 12:59:25 -0500 Subject: Remove erroneous new line from error message --- src/sdl/sdl_glimp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index 1f45551f..ffda45a0 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -149,10 +149,10 @@ static void GLimp_DetectAvailableModes(void) } numSDLModes = SDL_GetNumDisplayModes( display ); - modes = SDL_calloc( numSDLModes, sizeof( SDL_Rect )); + modes = SDL_calloc( numSDLModes, sizeof( SDL_Rect ) ); if ( !modes ) { - ri.Error( ERR_FATAL, "Out of memory\n" ); + ri.Error( ERR_FATAL, "Out of memory" ); } for( i = 0; i < numSDLModes; i++ ) -- cgit From 7b1fa0e3cc8c106a08ab8d7e12a0c40d2e2a7791 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 12 Jun 2015 14:22:37 -0500 Subject: Move image load function prototypes to tr_common.h The functions themselves are in code/renderercommon/tr_image_*.c --- src/renderercommon/tr_common.h | 14 ++++++++++++++ src/renderergl1/tr_local.h | 14 -------------- src/renderergl2/tr_local.h | 14 -------------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/src/renderercommon/tr_common.h b/src/renderercommon/tr_common.h index fe44f784..0dc5653d 100644 --- a/src/renderercommon/tr_common.h +++ b/src/renderercommon/tr_common.h @@ -129,6 +129,20 @@ void R_InitFreeType( void ); void R_DoneFreeType( void ); void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font); +/* +============================================================= + +IMAGE LOADERS + +============================================================= +*/ + +void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); +void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); +void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); +void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); +void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); + /* ==================================================================== diff --git a/src/renderergl1/tr_local.h b/src/renderergl1/tr_local.h index 6264af82..0d8131ec 100644 --- a/src/renderergl1/tr_local.h +++ b/src/renderergl1/tr_local.h @@ -1404,20 +1404,6 @@ int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, int startFrame, int endFrame, float frac, const char *tagName ); -/* -============================================================= - -IMAGE LOADERS - -============================================================= -*/ - -void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); -void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); -void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); -void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); -void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); - /* ============================================================= ============================================================= diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 95d87165..76cbe9c7 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -2278,20 +2278,6 @@ int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, int startFrame, int endFrame, float frac, const char *tagName ); -/* -============================================================= - -IMAGE LOADERS - -============================================================= -*/ - -void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); -void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); -void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); -void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); -void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); - /* ============================================================= ============================================================= -- cgit From e656dd81c4d86fc997986894316f13bc5c597e37 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 12 Jun 2015 14:31:58 -0500 Subject: Sort tr_image_*.c filenames in Makefile --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c634adae..6876a392 100644 --- a/Makefile +++ b/Makefile @@ -1564,11 +1564,11 @@ Q3R2OBJ = \ $(B)/renderergl2/tr_font.o \ $(B)/renderergl2/tr_glsl.o \ $(B)/renderergl2/tr_image.o \ - $(B)/renderergl2/tr_image_png.o \ - $(B)/renderergl2/tr_image_jpg.o \ $(B)/renderergl2/tr_image_bmp.o \ - $(B)/renderergl2/tr_image_tga.o \ + $(B)/renderergl2/tr_image_jpg.o \ $(B)/renderergl2/tr_image_pcx.o \ + $(B)/renderergl2/tr_image_png.o \ + $(B)/renderergl2/tr_image_tga.o \ $(B)/renderergl2/tr_init.o \ $(B)/renderergl2/tr_light.o \ $(B)/renderergl2/tr_main.o \ @@ -1630,11 +1630,11 @@ Q3ROBJ = \ $(B)/renderergl1/tr_flares.o \ $(B)/renderergl1/tr_font.o \ $(B)/renderergl1/tr_image.o \ - $(B)/renderergl1/tr_image_png.o \ - $(B)/renderergl1/tr_image_jpg.o \ $(B)/renderergl1/tr_image_bmp.o \ - $(B)/renderergl1/tr_image_tga.o \ + $(B)/renderergl1/tr_image_jpg.o \ $(B)/renderergl1/tr_image_pcx.o \ + $(B)/renderergl1/tr_image_png.o \ + $(B)/renderergl1/tr_image_tga.o \ $(B)/renderergl1/tr_init.o \ $(B)/renderergl1/tr_light.o \ $(B)/renderergl1/tr_main.o \ -- cgit From 2968a5e514c62e9df4528b43a3d089c965536b43 Mon Sep 17 00:00:00 2001 From: /dev/humancontroller Date: Thu, 18 Jun 2015 17:22:34 -0500 Subject: fix a stupid use of strcpy() strcpy() arguments may not overlap ! --- src/qcommon/q_shared.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcommon/q_shared.c b/src/qcommon/q_shared.c index f226603d..f5888633 100644 --- a/src/qcommon/q_shared.c +++ b/src/qcommon/q_shared.c @@ -1276,7 +1276,7 @@ void Info_RemoveKey_Big( char *s, const char *key ) { if (!strcmp (key, pkey) ) { - strcpy (start, s); // remove this part + memmove(start, s, strlen(s) + 1); // remove this part return; } -- cgit From cd73fc454e392d04156582984bccb4289307b2f3 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Sun, 28 Jun 2015 18:01:03 +0100 Subject: Check SDL_GetNumDisplayModes return value for errors --- src/sdl/sdl_glimp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index ffda45a0..2141c2bb 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -135,21 +135,21 @@ static void GLimp_DetectAvailableModes(void) { int i, j; char buf[ MAX_STRING_CHARS ] = { 0 }; - size_t numSDLModes; + int numSDLModes; SDL_Rect *modes; int numModes = 0; int display = SDL_GetWindowDisplayIndex( SDL_window ); + numSDLModes = SDL_GetNumDisplayModes( display ); SDL_DisplayMode windowMode; - if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 ) + if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) { ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected\n" ); return; } - numSDLModes = SDL_GetNumDisplayModes( display ); - modes = SDL_calloc( numSDLModes, sizeof( SDL_Rect ) ); + modes = SDL_calloc( (size_t)numSDLModes, sizeof( SDL_Rect ) ); if ( !modes ) { ri.Error( ERR_FATAL, "Out of memory" ); -- cgit From db361cbe859974162cf7c2d467b3209c692824f0 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 28 Jun 2015 16:29:10 -0500 Subject: Fix variable declaration for C89 compilers --- src/sdl/sdl_glimp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index 2141c2bb..b41da64c 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -139,9 +139,9 @@ static void GLimp_DetectAvailableModes(void) SDL_Rect *modes; int numModes = 0; + SDL_DisplayMode windowMode; int display = SDL_GetWindowDisplayIndex( SDL_window ); numSDLModes = SDL_GetNumDisplayModes( display ); - SDL_DisplayMode windowMode; if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) { -- cgit -- cgit From 6ddb2859cfc94d5aa07d962f9ff3268094e4d6f9 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 28 Jun 2015 17:55:47 -0500 Subject: Remove unused function WRITE_1BYTES from cl_avi.c --- src/client/cl_avi.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/client/cl_avi.c b/src/client/cl_avi.c index 723fbfa4..e4593923 100644 --- a/src/client/cl_avi.c +++ b/src/client/cl_avi.c @@ -122,17 +122,6 @@ static ID_INLINE void WRITE_2BYTES( int x ) bufIndex += 2; } -/* -=============== -WRITE_1BYTES -=============== -*/ -static ID_INLINE void WRITE_1BYTES( int x ) -{ - buffer[ bufIndex ] = x; - bufIndex += 1; -} - /* =============== START_CHUNK -- cgit From 86c35b23e4191e61af36b499aa4011b53f451b4a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 28 Jun 2015 18:02:48 -0500 Subject: Make cinematic times be int like CL_ScaledMilliseconds Cinematic's startTime and lastTime are always set from CL_ScaledMilliseconds which returns int and are converted back and forth to int and unsigned int. This fixes a warning that abs() is used on an unsigned int. --- src/client/cl_cin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/cl_cin.c b/src/client/cl_cin.c index 78a237ed..74660ed5 100644 --- a/src/client/cl_cin.c +++ b/src/client/cl_cin.c @@ -95,8 +95,8 @@ typedef struct { qboolean looping, holdAtEnd, dirty, alterGameState, silent, shader; fileHandle_t iFile; e_status status; - unsigned int startTime; - unsigned int lastTime; + int startTime; + int lastTime; long tfps; long RoQPlayed; long ROQSize; -- cgit -- cgit From f2b5400e983a4cf20da96783908a0a825e9f60c6 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 28 Jun 2015 18:24:55 -0500 Subject: Fix abs() being used for float in cl_input.c --- src/client/cl_input.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/cl_input.c b/src/client/cl_input.c index e09d7d75..fdd0c474 100644 --- a/src/client/cl_input.c +++ b/src/client/cl_input.c @@ -605,10 +605,10 @@ usercmd_t CL_CreateCmd( void ) { // draw debug graphs of turning for mouse testing if ( cl_debugMove->integer ) { if ( cl_debugMove->integer == 1 ) { - SCR_DebugGraph( abs(cl.viewangles[YAW] - oldAngles[YAW]) ); + SCR_DebugGraph( fabs(cl.viewangles[YAW] - oldAngles[YAW]) ); } if ( cl_debugMove->integer == 2 ) { - SCR_DebugGraph( abs(cl.viewangles[PITCH] - oldAngles[PITCH]) ); + SCR_DebugGraph( fabs(cl.viewangles[PITCH] - oldAngles[PITCH]) ); } } -- cgit From 657a3a4a11381deaff4f9328e16a7b3f3217fa21 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Tue, 30 Jun 2015 14:22:49 -0400 Subject: Add support for Aarch64 (ARM64) Add support for Aarch64, the 64-bit ARM architecture. --- Makefile | 4 ++++ src/qcommon/q_platform.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 6876a392..e4f042f4 100644 --- a/Makefile +++ b/Makefile @@ -322,6 +322,10 @@ ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu") else ifeq ($(ARCH),s390x) LIB=lib64 + else + ifeq ($(ARCH),aarch64) + LIB=lib64 + endif endif endif endif diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h index f04bf433..f3518bfc 100644 --- a/src/qcommon/q_platform.h +++ b/src/qcommon/q_platform.h @@ -208,6 +208,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define ARCH_STRING "sparc" #elif defined __arm__ #define ARCH_STRING "arm" +#elif defined __aarch64__ +#define ARCH_STRING "aarch64" #elif defined __cris__ #define ARCH_STRING "cris" #elif defined __hppa__ -- cgit -- cgit -- cgit From 00a83e798f7934962facba8e7864b215e1d94701 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sat, 4 Jul 2015 19:17:58 -0500 Subject: Apply greyscaling to fog blocks --- src/renderergl1/tr_shader.c | 17 +++++++++++++++++ src/renderergl2/tr_shader.c | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/renderergl1/tr_shader.c b/src/renderergl1/tr_shader.c index 2a66afd0..34d6d64e 100644 --- a/src/renderergl1/tr_shader.c +++ b/src/renderergl1/tr_shader.c @@ -1569,6 +1569,23 @@ static qboolean ParseShader( char **text ) return qfalse; } + if ( r_greyscale->integer ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + VectorSet( shader.fogParms.color, luminance, luminance, luminance ); + } + else if ( r_greyscale->value ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + shader.fogParms.color[0] = LERP( shader.fogParms.color[0], luminance, r_greyscale->value ); + shader.fogParms.color[1] = LERP( shader.fogParms.color[1], luminance, r_greyscale->value ); + shader.fogParms.color[2] = LERP( shader.fogParms.color[2], luminance, r_greyscale->value ); + } + token = COM_ParseExt( text, qfalse ); if ( !token[0] ) { diff --git a/src/renderergl2/tr_shader.c b/src/renderergl2/tr_shader.c index 4143b246..68b5cb60 100644 --- a/src/renderergl2/tr_shader.c +++ b/src/renderergl2/tr_shader.c @@ -1857,6 +1857,23 @@ static qboolean ParseShader( char **text ) return qfalse; } + if ( r_greyscale->integer ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + VectorSet( shader.fogParms.color, luminance, luminance, luminance ); + } + else if ( r_greyscale->value ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + shader.fogParms.color[0] = LERP( shader.fogParms.color[0], luminance, r_greyscale->value ); + shader.fogParms.color[1] = LERP( shader.fogParms.color[1], luminance, r_greyscale->value ); + shader.fogParms.color[2] = LERP( shader.fogParms.color[2], luminance, r_greyscale->value ); + } + token = COM_ParseExt( text, qfalse ); if ( !token[0] ) { -- cgit From a1cb4046bef1a81e8d19a1b2556c285da5cf3229 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sat, 4 Jul 2015 19:33:28 -0500 Subject: Don't fog 3D crosshair sprite --- src/renderergl1/tr_main.c | 4 ++++ src/renderergl2/tr_main.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/renderergl1/tr_main.c b/src/renderergl1/tr_main.c index 500bb788..b216d38f 100644 --- a/src/renderergl1/tr_main.c +++ b/src/renderergl1/tr_main.c @@ -1012,6 +1012,10 @@ int R_SpriteFogNum( trRefEntity_t *ent ) { return 0; } + if ( ent->e.renderfx & RF_CROSSHAIR ) { + return 0; + } + for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index 132ef309..287f95d3 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -1680,6 +1680,10 @@ int R_SpriteFogNum( trRefEntity_t *ent ) { return 0; } + if ( ent->e.renderfx & RF_CROSSHAIR ) { + return 0; + } + for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { -- cgit From b9d49e385f8a00f5b830b7547d9ad8070412af88 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sat, 4 Jul 2015 20:42:57 -0500 Subject: Fix Windows file list extension check Windows' Sys_ListFiles would add files that contain the extension anywhere, not only at the end of the file name. Example: "word.pk3omghacks" use to be loaded as a pk3 file. --- src/sys/sys_win32.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sys/sys_win32.c b/src/sys/sys_win32.c index a2554b89..d8e589b0 100644 --- a/src/sys/sys_win32.c +++ b/src/sys/sys_win32.c @@ -412,6 +412,7 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter intptr_t findhandle; int flag; int i; + int extLen; if (filter) { @@ -445,6 +446,8 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter flag = _A_SUBDIR; } + extLen = strlen( extension ); + Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension ); // search @@ -458,6 +461,14 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter do { if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) { + if (*extension) { + if ( strlen( findinfo.name ) < extLen || + Q_stricmp( + findinfo.name + strlen( findinfo.name ) - extLen, + extension ) ) { + continue; // didn't match + } + } if ( nfiles == MAX_FOUND_FILES - 1 ) { break; } -- cgit -- cgit -- cgit From adb15c5fd2468d8398916938b17204a40a85e366 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Thu, 9 Jul 2015 18:32:25 -0500 Subject: Remove unused fpucw from snapvector.asm It's usage was removed in commit 8a500d71. --- src/asm/snapvector.asm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/asm/snapvector.asm b/src/asm/snapvector.asm index 2836d4a8..59949f0f 100644 --- a/src/asm/snapvector.asm +++ b/src/asm/snapvector.asm @@ -36,10 +36,6 @@ ENDIF ssemask DWORD 0FFFFFFFFh, 0FFFFFFFFh, 0FFFFFFFFh, 00000000h ssecw DWORD 00001F80h -IFNDEF idx64 - fpucw WORD 037Fh -ENDIF - .code IFDEF idx64 -- cgit From 17abbc7123b1f79467d18c64b67235ce41c115c4 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Thu, 9 Jul 2015 22:28:08 -0500 Subject: Fix OpenGL2 ignoring last light grid point on each axis Also change light grid bounds clamping to make it more clear what invalid values are. --- src/renderergl1/tr_light.c | 2 +- src/renderergl2/tr_light.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/renderergl1/tr_light.c b/src/renderergl1/tr_light.c index 779451f1..bd79df55 100644 --- a/src/renderergl1/tr_light.c +++ b/src/renderergl1/tr_light.c @@ -152,7 +152,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { frac[i] = v - pos[i]; if ( pos[i] < 0 ) { pos[i] = 0; - } else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) { + } else if ( pos[i] > tr.world->lightGridBounds[i] - 1 ) { pos[i] = tr.world->lightGridBounds[i] - 1; } } diff --git a/src/renderergl2/tr_light.c b/src/renderergl2/tr_light.c index 5993959e..ec54eab4 100644 --- a/src/renderergl2/tr_light.c +++ b/src/renderergl2/tr_light.c @@ -157,7 +157,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { frac[i] = v - pos[i]; if ( pos[i] < 0 ) { pos[i] = 0; - } else if ( pos[i] >= world->lightGridBounds[i] - 1 ) { + } else if ( pos[i] > world->lightGridBounds[i] - 1 ) { pos[i] = world->lightGridBounds[i] - 1; } } @@ -190,7 +190,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { ignore = qfalse; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1<= world->lightGridBounds[j] - 1) + if ((pos[j] + 1) > world->lightGridBounds[j] - 1) { ignore = qtrue; // ignore values outside lightgrid } -- cgit From 3021d2b30e8d2b8456484cc9cd8adc30bda0a98e Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 17:53:17 -0500 Subject: Backport ignoring values outside lightgrid to OpenGL1 Fixes possibly of reading memory past end of lightGridData or reading wrong light grid data (wrapping around to next row). --- src/renderergl1/tr_light.c | 6 ++++++ src/renderergl2/tr_light.c | 10 ++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/renderergl1/tr_light.c b/src/renderergl1/tr_light.c index bd79df55..35233739 100644 --- a/src/renderergl1/tr_light.c +++ b/src/renderergl1/tr_light.c @@ -183,6 +183,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { data = gridData; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1< tr.world->lightGridBounds[j] - 1 ) { + break; // ignore values outside lightgrid + } factor *= frac[j]; data += gridStep[j]; } else { @@ -190,6 +193,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { } } + if ( j != 3 ) { + continue; + } if ( !(data[0]+data[1]+data[2]) ) { continue; // ignore samples in walls } diff --git a/src/renderergl2/tr_light.c b/src/renderergl2/tr_light.c index ec54eab4..317f4585 100644 --- a/src/renderergl2/tr_light.c +++ b/src/renderergl2/tr_light.c @@ -181,18 +181,15 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { byte *data; int lat, lng; vec3_t normal; - qboolean ignore; #if idppc float d0, d1, d2, d3, d4, d5; #endif factor = 1.0; data = gridData; - ignore = qfalse; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1< world->lightGridBounds[j] - 1) - { - ignore = qtrue; // ignore values outside lightgrid + if ( pos[j] + 1 > world->lightGridBounds[j] - 1 ) { + break; // ignore values outside lightgrid } factor *= frac[j]; data += gridStep[j]; @@ -201,8 +198,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { } } - if ( ignore ) + if ( j != 3 ) { continue; + } if (world->hdrLightGrid) { -- cgit From cc17bca3ad04ab60cfc66c9a4b8f1188878ae802 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 18:38:33 -0500 Subject: Fix range checks for numBorders in CM_AddFacetBevels Found by Coverity. --- src/qcommon/cm_patch.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/qcommon/cm_patch.c b/src/qcommon/cm_patch.c index 5a66b1b0..6fbcfbf6 100644 --- a/src/qcommon/cm_patch.c +++ b/src/qcommon/cm_patch.c @@ -877,7 +877,10 @@ void CM_AddFacetBevels( facet_t *facet ) { } if ( i == facet->numBorders ) { - if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n"); + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + continue; + } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = flipped; @@ -939,7 +942,10 @@ void CM_AddFacetBevels( facet_t *facet ) { } if ( i == facet->numBorders ) { - if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n"); + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + continue; + } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); for ( k = 0 ; k < facet->numBorders ; k++ ) { @@ -977,6 +983,10 @@ void CM_AddFacetBevels( facet_t *facet ) { #ifndef BSPC //add opposite plane + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + return; + } facet->borderPlanes[facet->numBorders] = facet->surfacePlane; facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = qtrue; -- cgit From fbcc2c5f397b8933be620221a266cb963df9b61e Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 18:56:15 -0500 Subject: Make more vm_x86 macros use braces so they work with if blah run macro MASK_REG in EmitMovEDXStack would incorrectly emit asm if 'andit' was 0. 'andit' would never be 0 though so it wasn't causing issues. Found by Coverity. --- src/qcommon/vm_x86.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/qcommon/vm_x86.c b/src/qcommon/vm_x86.c index 2056785d..cdf8ad56 100644 --- a/src/qcommon/vm_x86.c +++ b/src/qcommon/vm_x86.c @@ -204,19 +204,25 @@ static void EmitRexString(byte rex, const char *string) #define MASK_REG(modrm, mask) \ - EmitString("81"); \ - EmitString((modrm)); \ - Emit4((mask)) + do { \ + EmitString("81"); \ + EmitString((modrm)); \ + Emit4((mask)); \ + } while(0) // add bl, bytes #define STACK_PUSH(bytes) \ - EmitString("80 C3"); \ - Emit1(bytes) + do { \ + EmitString("80 C3"); \ + Emit1(bytes); \ + } while(0) // sub bl, bytes #define STACK_POP(bytes) \ - EmitString("80 EB"); \ - Emit1(bytes) + do { \ + EmitString("80 EB"); \ + Emit1(bytes); \ + } while(0) static void EmitCommand(ELastCommand command) { -- cgit From cd50d8d2e7d1085808b15e9e4be66a52289df013 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 19:31:37 -0500 Subject: Don't segfault in FS_CreatePath when there are no path seperators --- src/qcommon/files.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 576ad9d2..cedbeaf4 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -511,7 +511,9 @@ qboolean FS_CreatePath (char *OSPath) { // Skip creation of the root directory as it will always be there ofs = strchr( path, PATH_SEP ); - ofs++; + if ( ofs != NULL ) { + ofs++; + } for (; ofs != NULL && *ofs ; ofs++) { if (*ofs == PATH_SEP) { -- cgit From 948b565a2b0105d7c0530c78de7a4e005f73e6e8 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 20:35:22 -0500 Subject: Remove logically dead code in R_CheckFBO Found by Coverity. --- src/renderergl2/tr_fbo.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index f02e6cc7..c8ea0aeb 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -47,9 +47,6 @@ qboolean R_CheckFBO(const FBO_t * fbo) // an error occured switch (code) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name); break; -- cgit From 7ebcf42f808b8c1a209cabdaa6f879b8e1790036 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 20:41:41 -0500 Subject: Fix alloc size for default skin and single shader skin Found by Coverity. --- src/renderergl1/tr_image.c | 4 ++-- src/renderergl2/tr_image.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderergl1/tr_image.c b/src/renderergl1/tr_image.c index 6f58a5b2..e3a1f2eb 100644 --- a/src/renderergl1/tr_image.c +++ b/src/renderergl1/tr_image.c @@ -1556,7 +1556,7 @@ qhandle_t RE_RegisterSkin( const char *name ) { // If not a .skin file, load as a single shader if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); return hSkin; } @@ -1627,7 +1627,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 08894a4a..ef244d56 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -3121,7 +3121,7 @@ qhandle_t RE_RegisterSkin( const char *name ) { // If not a .skin file, load as a single shader if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); return hSkin; } @@ -3192,7 +3192,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } -- cgit -- cgit From 217f61a252c1e9d7da6fbfb8a30c421b4a264a8a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 12 Jul 2015 21:14:04 -0500 Subject: Remove logically dead code from CL_GetServerStatus Found by Coverity. --- src/client/cl_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 77df2e01..0199a520 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -149,7 +149,6 @@ typedef struct serverStatus_s } serverStatus_t; serverStatus_t cl_serverStatusList[MAX_SERVERSTATUSREQUESTS]; -int serverStatusCount; #if defined __USEA3D && defined __A3D_GEOM void hA3Dg_ExportRenderGeom (refexport_t *incoming_re); @@ -4005,11 +4004,7 @@ serverStatus_t *CL_GetServerStatus( netadr_t from ) { oldestTime = cl_serverStatusList[i].startTime; } } - if (oldest != -1) { - return &cl_serverStatusList[oldest]; - } - serverStatusCount++; - return &cl_serverStatusList[serverStatusCount & (MAX_SERVERSTATUSREQUESTS-1)]; + return &cl_serverStatusList[oldest]; } /* -- cgit -- cgit From 124894b4e9bb5ebe6d8e674340b3c1e053c690d1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 14 Jul 2015 22:51:53 +0100 Subject: Makefile: confine $(LIB) to the one platform that needs it, namely irix64 It isn't mentioned anywhere else, and deleting it from the Linux code path means we don't need to maintain an exhaustive list of 64-bit architectures. --- Makefile | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/Makefile b/Makefile index e4f042f4..dd2375c0 100644 --- a/Makefile +++ b/Makefile @@ -304,32 +304,12 @@ endif # SETUP AND BUILD -- LINUX ############################################################################# -## Defaults -LIB=lib - INSTALL=install MKDIR=mkdir EXTRA_FILES= CLIENT_EXTRA_FILES= ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) - - ifeq ($(ARCH),x86_64) - LIB=lib64 - else - ifeq ($(ARCH),ppc64) - LIB=lib64 - else - ifeq ($(ARCH),s390x) - LIB=lib64 - else - ifeq ($(ARCH),aarch64) - LIB=lib64 - endif - endif - endif - endif - BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ -pipe -DUSE_ICON CLIENT_CFLAGS += $(SDL_CFLAGS) @@ -811,6 +791,7 @@ else # ifeq netbsd ############################################################################# ifeq ($(PLATFORM),irix64) + LIB=lib ARCH=mips -- cgit From 3711115ee2d393b3fc3b7ef744803ca41ecc2ac6 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 14 Jul 2015 22:51:55 +0100 Subject: build: canonicalize all ARM variants to "arm", matching q_platform.h The ARCH in the Makefile must match the ARCH_STRING in q_platform.h; otherwise, ioquake3 will install (for instance) uiARCH.so but look for uiARCH_STRING.so, which isn't going to go well (particularly for the modular renderer). Like i386, but unlike most (all?) other Linux platforms, uname -m on 32-bit ARM machines can have various results starting with "arm", depending on the specific CPU version (e.g. Raspberry Pi is armv6l, RPi2 is armv7l). Again similar to the x86 family, it's appropriate for them to share an architecture suffix; q_platform.h has traditionally used "arm" so let's use that. 64-bit ARM makes a clean break from this, much like 64-bit x86 does: uname -m produces a string not starting with arm (specifically "aarch64"), and gcc predefines __aarch64__ instead of __arm__. As a result, it is unaffected by this change. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index dd2375c0..48f94da4 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ COMPILE_PLATFORM=$(shell uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]'|sed -e 's/\//_/g') -COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/) +COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/ | sed -e 's/^arm.*/arm/') ifeq ($(COMPILE_PLATFORM),sunos) # Solaris uname and GNU uname differ -- cgit From f0e19948fe871198ea9c049f721ab2caf458bcb7 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 14 Jul 2015 22:51:57 +0100 Subject: build: define ARCH_STRING in Makefile on Linux and other GNU platforms GNU platforms (Linux, kFreeBSD, Hurd) have endian.h to determine endianness, so all architectures except x86_64 are in fact treated identically, except that their ARCH_STRING is different. The ARCH_STRING must always be identical to the ARCH from the Makefile, otherwise the engine will not find its cgame, game and ui plugins under their expected names and startup will fail. If we pass it in from the Makefile, then an identical value is guaranteed, and we can get rid of an increasingly long list of defined(__some_cpu__) tests. The one remaining quirk is that we test __x86_64__ to determine whether to define idx64; I've kept that, but separated it from the ARCH_STRING. On non-Linux platforms we only support a few architectures anyway, so keeping the list up to date is less of a burden; *BSD porters could probably use the same technique to get support for lots of architectures with little effort, but I have not done that here, because I cannot test it. Windows must continue to support preprocessor-based architecture tests in any case, so that the MSVC solutions (which do not use the Makefile) can continue to work. However, Windows only runs on a few CPU families, so this shouldn't be a significant burden in practice. When cross-compiling, the tools are compiled for the build architecture (COMPILE_PLATFORM, COMPILE_ARCH) rather than the host architecture (PLATFORM, ARCH), so define ARCH_STRING to COMPILE_ARCH on a GNU COMPILE_PLATFORM. --- Makefile | 6 +++++- src/qcommon/q_platform.h | 35 +++++------------------------------ 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index 48f94da4..83431fdc 100644 --- a/Makefile +++ b/Makefile @@ -309,9 +309,13 @@ MKDIR=mkdir EXTRA_FILES= CLIENT_EXTRA_FILES= +ifneq (,$(findstring "$(COMPILE_PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) + TOOLS_CFLAGS += -DARCH_STRING=\"$(COMPILE_ARCH)\" +endif + ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ - -pipe -DUSE_ICON + -pipe -DUSE_ICON -DARCH_STRING=\\\"$(ARCH)\\\" CLIENT_CFLAGS += $(SDL_CFLAGS) OPTIMIZEVM = -O3 diff --git a/src/qcommon/q_platform.h b/src/qcommon/q_platform.h index f3518bfc..34a93626 100644 --- a/src/qcommon/q_platform.h +++ b/src/qcommon/q_platform.h @@ -186,38 +186,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define PATH_SEP '/' -#if defined __i386__ -#define ARCH_STRING "x86" -#elif defined __x86_64__ +#if !defined(ARCH_STRING) +# error ARCH_STRING should be defined by the Makefile +#endif + +#if defined __x86_64__ #undef idx64 #define idx64 1 -#define ARCH_STRING "x86_64" -#elif defined __powerpc64__ -#define ARCH_STRING "ppc64" -#elif defined __powerpc__ -#define ARCH_STRING "ppc" -#elif defined __s390__ -#define ARCH_STRING "s390" -#elif defined __s390x__ -#define ARCH_STRING "s390x" -#elif defined __ia64__ -#define ARCH_STRING "ia64" -#elif defined __alpha__ -#define ARCH_STRING "alpha" -#elif defined __sparc__ -#define ARCH_STRING "sparc" -#elif defined __arm__ -#define ARCH_STRING "arm" -#elif defined __aarch64__ -#define ARCH_STRING "aarch64" -#elif defined __cris__ -#define ARCH_STRING "cris" -#elif defined __hppa__ -#define ARCH_STRING "hppa" -#elif defined __mips__ -#define ARCH_STRING "mips" -#elif defined __sh__ -#define ARCH_STRING "sh" #endif #if __FLOAT_WORD_ORDER == __BIG_ENDIAN -- cgit From 78d3929f526d06b1879c565ed08b337ba6138cae Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 22 Jul 2015 08:15:18 +0100 Subject: build: if tput fails, fall back to a reasonable text width If TERM is not set (which can happen in autobuilders and other batch environments), or if tput cannot determine the number of columns for some other reason, then it can fail and not produce any output. Prior to this change, that would result in passing field width -4 to fmt, which is an error and causes fmt to produce no output. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 83431fdc..408909f3 100644 --- a/Makefile +++ b/Makefile @@ -1179,7 +1179,7 @@ ifeq ($(BUILD_MASTER_SERVER),1) endif ifneq ($(call bin_path, tput),) - TERM_COLUMNS=$(shell echo $$((`tput cols`-4))) + TERM_COLUMNS=$(shell if c=`tput cols`; then echo $$(($$c-4)); else echo 76; fi) else TERM_COLUMNS=76 endif -- cgit From 95cc01fb25e20822fe9b091702789111cc5d1b8b Mon Sep 17 00:00:00 2001 From: Pan7 Date: Fri, 24 Jul 2015 22:56:00 +0200 Subject: SDL_Init zero check --- src/sdl/sdl_glimp.c | 2 +- src/sdl/sdl_input.c | 2 +- src/sdl/sdl_snd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index b41da64c..9f86dd9e 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -536,7 +536,7 @@ static qboolean GLimp_StartDriverAndSetMode( qboolean failSafe, qboolean fullscr { const char *driverName; - if (SDL_Init(SDL_INIT_VIDEO) == -1) + if (SDL_Init(SDL_INIT_VIDEO) != 0) { ri.Printf( PRINT_ALL, "SDL_Init( SDL_INIT_VIDEO ) FAILED (%s)\n", SDL_GetError()); return qfalse; diff --git a/src/sdl/sdl_input.c b/src/sdl/sdl_input.c index 2b466744..fbe90d08 100644 --- a/src/sdl/sdl_input.c +++ b/src/sdl/sdl_input.c @@ -486,7 +486,7 @@ static void IN_InitJoystick( void ) if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { Com_DPrintf("Calling SDL_Init(SDL_INIT_JOYSTICK)...\n"); - if (SDL_Init(SDL_INIT_JOYSTICK) == -1) + if (SDL_Init(SDL_INIT_JOYSTICK) != 0) { Com_DPrintf("SDL_Init(SDL_INIT_JOYSTICK) failed: %s\n", SDL_GetError()); return; diff --git a/src/sdl/sdl_snd.c b/src/sdl/sdl_snd.c index a087c486..9420f0ba 100644 --- a/src/sdl/sdl_snd.c +++ b/src/sdl/sdl_snd.c @@ -157,7 +157,7 @@ qboolean SNDDMA_Init(void) if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_Init(SDL_INIT_AUDIO) == -1) + if (SDL_Init(SDL_INIT_AUDIO) != 0) { Com_Printf( "FAILED (%s)\n", SDL_GetError( ) ); return qfalse; -- cgit From f3d9ff7b490b6f3ce355e3f4441f7758340a096b Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 03:21:45 +0200 Subject: SDL_FALSE/TRUE for SDL_SetWindowGrab --- src/sdl/sdl_input.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sdl/sdl_input.c b/src/sdl/sdl_input.c index fbe90d08..700834c2 100644 --- a/src/sdl/sdl_input.c +++ b/src/sdl/sdl_input.c @@ -366,7 +366,7 @@ static void IN_ActivateMouse( void ) if( !mouseActive ) { SDL_SetRelativeMouseMode( SDL_TRUE ); - SDL_SetWindowGrab( SDL_window, 1 ); + SDL_SetWindowGrab( SDL_window, SDL_TRUE ); IN_GobbleMotionEvents( ); } @@ -377,9 +377,9 @@ static void IN_ActivateMouse( void ) if( in_nograb->modified || !mouseActive ) { if( in_nograb->integer ) - SDL_SetWindowGrab( SDL_window, 0 ); + SDL_SetWindowGrab( SDL_window, SDL_FALSE ); else - SDL_SetWindowGrab( SDL_window, 1 ); + SDL_SetWindowGrab( SDL_window, SDL_TRUE ); in_nograb->modified = qfalse; } @@ -416,7 +416,7 @@ static void IN_DeactivateMouse( void ) { IN_GobbleMotionEvents( ); - SDL_SetWindowGrab( SDL_window, 0 ); + SDL_SetWindowGrab( SDL_window, SDL_FALSE ); SDL_SetRelativeMouseMode( SDL_FALSE ); // Don't warp the mouse unless the cursor is within the window -- cgit From d3e4081ba8961e9d0eec4927b4a83b084dc02723 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 04:31:27 +0200 Subject: SDL_SetWindowGammaRamp check --- src/sdl/sdl_gamma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdl/sdl_gamma.c b/src/sdl/sdl_gamma.c index 0029db18..2f807055 100644 --- a/src/sdl/sdl_gamma.c +++ b/src/sdl/sdl_gamma.c @@ -89,6 +89,9 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned } } - SDL_SetWindowGammaRamp(SDL_window, table[0], table[1], table[2]); + if (SDL_SetWindowGammaRamp(SDL_window, table[0], table[1], table[2]) < 0) + { + ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowGammaRamp() failed.\n" ); + } } -- cgit From 6a1b563be8d358a7d4af5b43307ace4c5f2c6a99 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 13:03:47 +0200 Subject: SDL_GetWindowDisplayIndex check --- src/sdl/sdl_glimp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index 9f86dd9e..e979ba1f 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -141,6 +141,11 @@ static void GLimp_DetectAvailableModes(void) SDL_DisplayMode windowMode; int display = SDL_GetWindowDisplayIndex( SDL_window ); + if( display < 0 ) + { + ri.Printf( PRINT_WARNING, "Couldn't get window display index, no resolutions detected\n" ); + return; + } numSDLModes = SDL_GetNumDisplayModes( display ); if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) -- cgit From 969f68f3c17199073643a138f12f9b6dae0717bb Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 13:54:29 +0200 Subject: SDL_CreateWindow NULL check --- src/sdl/sdl_glimp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index e979ba1f..d7536794 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -460,7 +460,7 @@ static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen, qboolean nobor #endif if( ( SDL_window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, - glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) + glConfig.vidWidth, glConfig.vidHeight, flags ) ) == NULL ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; -- cgit From fc530362b74857609f1a73bbe2339f0609b04a8f Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 15:41:41 +0200 Subject: Added SDL_GetError() --- src/sdl/sdl_glimp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index d7536794..e4c816c0 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -143,14 +143,14 @@ static void GLimp_DetectAvailableModes(void) int display = SDL_GetWindowDisplayIndex( SDL_window ); if( display < 0 ) { - ri.Printf( PRINT_WARNING, "Couldn't get window display index, no resolutions detected\n" ); + ri.Printf( PRINT_WARNING, "Couldn't get window display index, no resolutions detected: %s\n", SDL_GetError() ); return; } numSDLModes = SDL_GetNumDisplayModes( display ); if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) { - ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected\n" ); + ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected: %s\n", SDL_GetError() ); return; } -- cgit From 12c86c4d96fb34625ac439458055a919956e3f7c Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 15:45:21 +0200 Subject: Added SDL_GetError() --- src/sdl/sdl_gamma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/sdl_gamma.c b/src/sdl/sdl_gamma.c index 2f807055..7e030683 100644 --- a/src/sdl/sdl_gamma.c +++ b/src/sdl/sdl_gamma.c @@ -91,7 +91,7 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned if (SDL_SetWindowGammaRamp(SDL_window, table[0], table[1], table[2]) < 0) { - ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowGammaRamp() failed.\n" ); + ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowGammaRamp() failed: %s\n", SDL_GetError() ); } } -- cgit From 22b5d7b96190ada24158a9ba41fee893f1a5cb46 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 19:46:07 +0200 Subject: SDL_GetWindowDisplayIndex() check2 --- src/sdl/sdl_glimp.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index e4c816c0..efe712fd 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -258,9 +258,15 @@ static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen, qboolean nobor // If a window exists, note its display index if( SDL_window != NULL ) + { display = SDL_GetWindowDisplayIndex( SDL_window ); + if( display < 0 ) + { + ri.Printf( PRINT_DEVELOPER, "SDL_GetWindowDisplayIndex() failed: %s\n", SDL_GetError() ); + } + } - if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) + if( display >= 0 && SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { glConfig.displayAspect = (float)desktopMode.w / (float)desktopMode.h; -- cgit From 483b91152ca6f2449bf632214f32a8ebbce3fc7d Mon Sep 17 00:00:00 2001 From: Pan7 Date: Sun, 26 Jul 2015 20:23:48 +0200 Subject: SDL_GL_SetSwapInterval() check --- src/sdl/sdl_glimp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sdl/sdl_glimp.c b/src/sdl/sdl_glimp.c index efe712fd..fed3fc5b 100644 --- a/src/sdl/sdl_glimp.c +++ b/src/sdl/sdl_glimp.c @@ -507,7 +507,10 @@ static int GLimp_SetMode( qboolean failSafe, qboolean fullscreen, qboolean nobor qglClear( GL_COLOR_BUFFER_BIT ); SDL_GL_SwapWindow( SDL_window ); - SDL_GL_SetSwapInterval( r_swapInterval->integer ); + if( SDL_GL_SetSwapInterval( r_swapInterval->integer ) == -1 ) + { + ri.Printf( PRINT_DEVELOPER, "SDL_GL_SetSwapInterval failed: %s\n", SDL_GetError( ) ); + } glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; -- cgit From b595499c2ca57ca1995f46b026cba44548ae81e6 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 26 Jul 2015 21:27:25 -0500 Subject: Fix 'Invalid architecture' message in make-macosx-app.sh --- make-macosx-app.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make-macosx-app.sh b/make-macosx-app.sh index 13f6f70d..cea20967 100755 --- a/make-macosx-app.sh +++ b/make-macosx-app.sh @@ -42,7 +42,7 @@ if [ "$2" != "" ]; then elif [ "$2" == "ppc" ]; then CURRENT_ARCH="ppc" else - echo "Invalid architecture: $1" + echo "Invalid architecture: $2" echo "Valid architectures are:" echo " x86" echo " x86_64" -- cgit From eee640bf1623d3d418774de0f1e94de257b81e7e Mon Sep 17 00:00:00 2001 From: Pan7 Date: Mon, 27 Jul 2015 20:38:20 +0200 Subject: qcurl_multi_remove_handle check --- src/client/cl_curl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index c3d0c7c8..07633917 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -179,8 +179,13 @@ void CL_cURL_Cleanup(void) { if(clc.downloadCURLM) { if(clc.downloadCURL) { - qcurl_multi_remove_handle(clc.downloadCURLM, + CURLMcode result; + + result = qcurl_multi_remove_handle(clc.downloadCURLM, clc.downloadCURL); + if(result != CURLM_OK) { + Com_DPrintf("qcurl_multi_remove_handle failed: %s\n", curl_multi_strerror(result)); + } qcurl_easy_cleanup(clc.downloadCURL); } qcurl_multi_cleanup(clc.downloadCURLM); -- cgit From a5ed81a9a6934bd6f0567307832b33d6b28dc9da Mon Sep 17 00:00:00 2001 From: Pan7 Date: Mon, 27 Jul 2015 21:04:47 +0200 Subject: qcurl_multi_strerror not curl_multi_strerror --- src/client/cl_curl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 07633917..e3cf6ddc 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -184,7 +184,7 @@ void CL_cURL_Cleanup(void) result = qcurl_multi_remove_handle(clc.downloadCURLM, clc.downloadCURL); if(result != CURLM_OK) { - Com_DPrintf("qcurl_multi_remove_handle failed: %s\n", curl_multi_strerror(result)); + Com_DPrintf("qcurl_multi_remove_handle failed: %s\n", qcurl_multi_strerror(result)); } qcurl_easy_cleanup(clc.downloadCURL); } -- cgit From 208af524e60c88bae53eedfa7012f962cacd1e15 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Tue, 28 Jul 2015 17:23:31 +0200 Subject: qcurl_easy_setopt dev warning --- src/client/cl_curl.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index e3cf6ddc..3ec1e354 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -215,6 +215,16 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } +CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, va_list args) +{ + CURLcode result; + + result = qcurl_easy_setopt(curl, option, args); + if(result != CURLE_OK) { + Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); + } +} + void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { CURLMcode result; @@ -254,23 +264,23 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) } if(com_developer->integer) - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, - va("Tremulous://%s", NET_AdrToString(clc.serverAddress))); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_VERBOSE, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_REFERER, + va("Tremulous://%s", NET_AdrToString(clc.serverAddress))); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FAILONERROR, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); -- cgit From 3175cb56dfe31d511ba98195c7f778af69d6a7ad Mon Sep 17 00:00:00 2001 From: Pan7 Date: Wed, 29 Jul 2015 13:32:00 +0200 Subject: qcurl_multi_cleanup check --- src/client/cl_curl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 3ec1e354..c3530d72 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -178,9 +178,9 @@ void CL_cURL_Shutdown( void ) void CL_cURL_Cleanup(void) { if(clc.downloadCURLM) { - if(clc.downloadCURL) { - CURLMcode result; + CURLMcode result; + if(clc.downloadCURL) { result = qcurl_multi_remove_handle(clc.downloadCURLM, clc.downloadCURL); if(result != CURLM_OK) { @@ -188,7 +188,10 @@ void CL_cURL_Cleanup(void) } qcurl_easy_cleanup(clc.downloadCURL); } - qcurl_multi_cleanup(clc.downloadCURLM); + result = qcurl_multi_cleanup(clc.downloadCURLM); + if(result != CURLM_OK) { + Com_DPrintf("CL_cURL_Cleanup: qcurl_multi_cleanup failed: %s\n", qcurl_multi_strerror(result)); + } clc.downloadCURLM = NULL; clc.downloadCURL = NULL; } -- cgit From 42e7af1602cedbc7dcb440e2298bcfdc75b437f4 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Wed, 29 Jul 2015 13:39:27 +0100 Subject: Return the result from qcurl_easy_setopt_warn --- src/client/cl_curl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index c3530d72..475398d1 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -226,6 +226,8 @@ CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, va_list args) if(result != CURLE_OK) { Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); } + + return result; } void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) -- cgit From 4865b932d3e2c0dad8a7a53374726c149e9c247a Mon Sep 17 00:00:00 2001 From: Pan7 Date: Wed, 29 Jul 2015 16:44:59 +0200 Subject: Add missing qcurl handle cleanup --- src/client/cl_curl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 475398d1..2288b7cf 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -296,6 +296,8 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) } result = qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); if(result != CURLM_OK) { + qcurl_easy_cleanup(clc.downloadCURL); + clc.downloadCURL = NULL; Com_Error(ERR_DROP,"CL_cURL_BeginDownload: qcurl_multi_add_handle() failed: %s", qcurl_multi_strerror(result)); return; } -- cgit From 4cbb09b086c876d18aedd13f679b1ca071e89f62 Mon Sep 17 00:00:00 2001 From: Pan7 Date: Thu, 30 Jul 2015 17:09:51 +0200 Subject: Fix va_list warning --- src/client/cl_curl.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 2288b7cf..572ed550 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -218,11 +218,14 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } -CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, va_list args) +CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) { CURLcode result; + va_list args; + va_start(args, option); result = qcurl_easy_setopt(curl, option, args); + va_end(args); if(result != CURLE_OK) { Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); } -- cgit -- cgit -- cgit From 8c3004cd645986de6471164c764c4a38b88f8681 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 18 Aug 2015 17:38:43 -0500 Subject: Ignore MSVC non-project files Ignore auto generated or user configuration for MSVC projects. Note: .user is ignored in Xcode section but applies to MSVC too. Patch by @shearer12345. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index cf567edb..ecb8d2c8 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ profile # Microsoft Visual Studio #################### *.sdf +*.opensdf +*.suo -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit -- cgit From eeb8d9fe1eddd1581966bda53ffb9eb1befbeb62 Mon Sep 17 00:00:00 2001 From: "Zachary J. Slater" Date: Fri, 28 Aug 2015 10:36:46 -0700 Subject: more helpful error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Can’t find your pak0.pk3? Here’s where we tried looking. --- src/qcommon/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcommon/files.c b/src/qcommon/files.c index cedbeaf4..0c88cc1f 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -2705,7 +2705,7 @@ void FS_Path_f( void ) { searchpath_t *s; int i; - Com_Printf ("Current search path:\n"); + Com_Printf ("We tried looking in the current search path:\n"); for (s = fs_searchpaths; s; s = s->next) { if (s->pack) { Com_Printf ("%s (%i files)\n", s->pack->pakFilename, s->pack->numfiles); -- cgit From 6ca1cc925f816892b08925c90373a7b7e4ba8dbd Mon Sep 17 00:00:00 2001 From: "Zachary J. Slater" Date: Fri, 28 Aug 2015 18:19:29 -0700 Subject: Better language, less tense --- src/qcommon/files.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 0c88cc1f..ab2358d8 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -2705,7 +2705,7 @@ void FS_Path_f( void ) { searchpath_t *s; int i; - Com_Printf ("We tried looking in the current search path:\n"); + Com_Printf ("We are looking in the current search path:\n"); for (s = fs_searchpaths; s; s = s->next) { if (s->pack) { Com_Printf ("%s (%i files)\n", s->pack->pakFilename, s->pack->numfiles); -- cgit From ae6435c1b3064f44702535c0df99e42e9752a1df Mon Sep 17 00:00:00 2001 From: Dion Williams Date: Mon, 7 Sep 2015 11:29:15 +0100 Subject: Fix Cvar_Unset not notifying cvar_modifiedFlags Upstream: JACoders/OpenJK@9a5e9e87ff2d1302261978fa3f1adafb851bd6d6 --- src/qcommon/cvar.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qcommon/cvar.c b/src/qcommon/cvar.c index 336f45b0..d22679e8 100644 --- a/src/qcommon/cvar.c +++ b/src/qcommon/cvar.c @@ -1118,6 +1118,9 @@ cvar_t *Cvar_Unset(cvar_t *cv) { cvar_t *next = cv->next; + // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) + cvar_modifiedFlags |= cv->flags; + if(cv->name) Z_Free(cv->name); if(cv->string) -- cgit From 88bdc8f9da2a1d3f31de758f1a2b75f87284b133 Mon Sep 17 00:00:00 2001 From: Dion Williams Date: Mon, 7 Sep 2015 11:32:43 +0100 Subject: Ensure reads from /dev/urandom are unbuffered Upstream: JACoders/OpenJK@de6a9dfd40065ae9a5a2b0b3ef701feee8dac867 --- src/sys/sys_unix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sys/sys_unix.c b/src/sys/sys_unix.c index dd77e0da..22af0fcf 100644 --- a/src/sys/sys_unix.c +++ b/src/sys/sys_unix.c @@ -116,6 +116,8 @@ qboolean Sys_RandomBytes( byte *string, int len ) if( !fp ) return qfalse; + setvbuf( fp, NULL, _IONBF, 0 ); // don't buffer reads from /dev/urandom + if( fread( string, sizeof( byte ), len, fp ) != len ) { fclose( fp ); -- cgit From 9bb0f2a8841f4bf5d1af9e516e547ecdfdb6f0d8 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Wed, 9 Sep 2015 22:32:12 +0100 Subject: Fix wonky va_list usage --- src/client/cl_curl.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 572ed550..80aefabe 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -218,14 +218,11 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } -CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) +static CURLcode qcurl_easy_setopt_warn_valist(CURL *curl, CURLoption option, va_list args) { CURLcode result; - va_list args; - va_start(args, option); result = qcurl_easy_setopt(curl, option, args); - va_end(args); if(result != CURLE_OK) { Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); } @@ -233,6 +230,18 @@ CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) return result; } +CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) +{ + CURLcode result; + + va_list argp; + va_start(argp, option); + result = qcurl_easy_setopt_warn_valist(curl, option, argp); + va_end(argp); + + return result; +} + void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { CURLMcode result; -- cgit From 35b1badb5a50ff044eaa2b1e305cf201e3acbf3b Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Wed, 9 Sep 2015 23:33:36 +0100 Subject: Fix the wonky fix to the wonky va_list usage --- src/client/cl_curl.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 80aefabe..7f23e7df 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -218,25 +218,27 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } -static CURLcode qcurl_easy_setopt_warn_valist(CURL *curl, CURLoption option, va_list args) -{ - CURLcode result; - - result = qcurl_easy_setopt(curl, option, args); - if(result != CURLE_OK) { - Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); - } - - return result; -} - CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) { CURLcode result; va_list argp; va_start(argp, option); - result = qcurl_easy_setopt_warn_valist(curl, option, argp); + + if(option < CURLOPTTYPE_OBJECTPOINT) { + long longValue = va_arg(argp, long); + result = qcurl_easy_setopt_warn(curl, option, longValue); + } else if(option < CURLOPTTYPE_OFF_T) { + void *pointerValue = va_arg(argp, void *); + result = qcurl_easy_setopt_warn(curl, option, pointerValue); + } else { + curl_off_t offsetValue = va_arg(argp, curl_off_t); + result = qcurl_easy_setopt_warn(curl, option, offsetValue); + } + + if(result != CURLE_OK) { + Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); + } va_end(argp); return result; -- cgit -- cgit -- cgit From 932b463906c431acb4c7d5f906ed1dc6eb9a0ede Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Thu, 17 Sep 2015 18:46:01 -0500 Subject: Use correct array size for facets in cm_patch.c --- src/qcommon/cm_patch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qcommon/cm_patch.c b/src/qcommon/cm_patch.c index 6fbcfbf6..5f55e9d4 100644 --- a/src/qcommon/cm_patch.c +++ b/src/qcommon/cm_patch.c @@ -419,7 +419,7 @@ static int numPlanes; static patchPlane_t planes[MAX_PATCH_PLANES]; static int numFacets; -static facet_t facets[MAX_PATCH_PLANES]; //maybe MAX_FACETS ?? +static facet_t facets[MAX_FACETS]; #define NORMAL_EPSILON 0.0001 #define DIST_EPSILON 0.02 -- cgit From 50a9ce3114f3fc4533227b5d59917b19162c16e6 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 20 Sep 2015 18:50:36 -0500 Subject: Early out of Cmd_CompleteArgument and Cmd_SetCommandCompletionFunc Reported by Ensiform. --- src/qcommon/cmd.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qcommon/cmd.c b/src/qcommon/cmd.c index 44a6f0ea..48489eff 100644 --- a/src/qcommon/cmd.c +++ b/src/qcommon/cmd.c @@ -706,6 +706,7 @@ void Cmd_SetCommandCompletionFunc( const char *command, completionFunc_t complet for( cmd = cmd_functions; cmd; cmd = cmd->next ) { if( !Q_stricmp( command, cmd->name ) ) { cmd->complete = complete; + return; } } } @@ -782,8 +783,11 @@ void Cmd_CompleteArgument( const char *command, char *args, int argNum ) { cmd_function_t *cmd; for( cmd = cmd_functions; cmd; cmd = cmd->next ) { - if( !Q_stricmp( command, cmd->name ) && cmd->complete ) { - cmd->complete( args, argNum ); + if( !Q_stricmp( command, cmd->name ) ) { + if ( cmd->complete ) { + cmd->complete( args, argNum ); + } + return; } } } -- cgit -- cgit -- cgit -- cgit From 8c0a10af38306b585ae2a5dd2456a37647e9bb02 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 25 Sep 2015 04:52:17 -0700 Subject: Search for mods in steam path as well as home and base paths. --- src/qcommon/files.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/qcommon/files.c b/src/qcommon/files.c index ab2358d8..02235bcf 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -2448,6 +2448,8 @@ int FS_GetModList( char *listbuf, int bufsize ) { int dummy; char **pFiles0 = NULL; char **pFiles1 = NULL; + char **pFiles2 = NULL; + char **pFiles3 = NULL; qboolean bDrop = qfalse; *listbuf = 0; @@ -2455,9 +2457,12 @@ int FS_GetModList( char *listbuf, int bufsize ) { pFiles0 = Sys_ListFiles( fs_homepath->string, NULL, NULL, &dummy, qtrue ); pFiles1 = Sys_ListFiles( fs_basepath->string, NULL, NULL, &dummy, qtrue ); + pFiles2 = Sys_ListFiles( fs_steampath->string, NULL, NULL, &dummy, qtrue ); // we searched for mods in the three paths // it is likely that we have duplicate names now, which we will cleanup below - pFiles = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); + pFiles3 = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); + pFiles = Sys_ConcatenateFileLists( pFiles2, pFiles3 ); + nPotential = Sys_CountFileList(pFiles); for ( i = 0 ; i < nPotential ; i++ ) { @@ -2499,6 +2504,15 @@ int FS_GetModList( char *listbuf, int bufsize ) { Sys_FreeFileList( pPaks ); } + /* try on steam path */ + if ( nPaks <= 0 ) + { + path = FS_BuildOSPath( fs_steampath->string, name, "" ); + nPaks = 0; + pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse ); + Sys_FreeFileList( pPaks ); + } + if (nPaks > 0) { nLen = strlen(name) + 1; // nLen is the length of the mod path @@ -3227,6 +3241,9 @@ static void FS_Startup( const char *gameName ) // check for additional base game so mods can be based upon other mods if ( fs_basegame->string[0] && Q_stricmp( fs_basegame->string, gameName ) ) { + if (fs_steampath->string[0]) { + FS_AddGameDirectory(fs_steampath->string, fs_basegame->string); + } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_basegame->string); } @@ -3237,6 +3254,9 @@ static void FS_Startup( const char *gameName ) // check for additional game folder for mods if ( fs_gamedirvar->string[0] && Q_stricmp( fs_gamedirvar->string, gameName ) ) { + if (fs_steampath->string[0]) { + FS_AddGameDirectory(fs_steampath->string, fs_gamedirvar->string); + } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string); } -- cgit From 360299211844847b652e4d4c27f0b2d5141b0aaa Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Fri, 25 Sep 2015 22:49:55 +0100 Subject: Effectively revert c2e146c1 --- src/client/cl_curl.c | 52 +++++++++++++--------------------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 7f23e7df..1570885b 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -218,32 +218,6 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } -CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) -{ - CURLcode result; - - va_list argp; - va_start(argp, option); - - if(option < CURLOPTTYPE_OBJECTPOINT) { - long longValue = va_arg(argp, long); - result = qcurl_easy_setopt_warn(curl, option, longValue); - } else if(option < CURLOPTTYPE_OFF_T) { - void *pointerValue = va_arg(argp, void *); - result = qcurl_easy_setopt_warn(curl, option, pointerValue); - } else { - curl_off_t offsetValue = va_arg(argp, curl_off_t); - result = qcurl_easy_setopt_warn(curl, option, offsetValue); - } - - if(result != CURLE_OK) { - Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); - } - va_end(argp); - - return result; -} - void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { CURLMcode result; @@ -283,23 +257,23 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) } if(com_developer->integer) - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_VERBOSE, 1); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_REFERER, + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("Tremulous://%s", NET_AdrToString(clc.serverAddress))); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEFUNCTION, + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FAILONERROR, 1); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); - qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); + qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); -- cgit From bbd6e0b9bb8d952198c43c24ee90fd5fe73aaeca Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Sat, 26 Sep 2015 10:54:16 +0100 Subject: Now with less infinite recursion --- src/client/cl_curl.c | 54 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/client/cl_curl.c b/src/client/cl_curl.c index 1570885b..166fb1dc 100644 --- a/src/client/cl_curl.c +++ b/src/client/cl_curl.c @@ -218,6 +218,32 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } +CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) +{ + CURLcode result; + + va_list argp; + va_start(argp, option); + + if(option < CURLOPTTYPE_OBJECTPOINT) { + long longValue = va_arg(argp, long); + result = qcurl_easy_setopt(curl, option, longValue); + } else if(option < CURLOPTTYPE_OFF_T) { + void *pointerValue = va_arg(argp, void *); + result = qcurl_easy_setopt(curl, option, pointerValue); + } else { + curl_off_t offsetValue = va_arg(argp, curl_off_t); + result = qcurl_easy_setopt(curl, option, offsetValue); + } + + if(result != CURLE_OK) { + Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); + } + va_end(argp); + + return result; +} + void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { CURLMcode result; @@ -257,23 +283,23 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) } if(com_developer->integer) - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, - va("Tremulous://%s", NET_AdrToString(clc.serverAddress))); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_VERBOSE, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_REFERER, + va("Tremulous://%s", NET_AdrToString(clc.serverAddress))); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FAILONERROR, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); -- cgit From 53f0839ec8ecfd1b79a77bcd0949368fa4d4cf06 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Sun, 4 Oct 2015 21:11:24 +0100 Subject: Fix check for empty rconpassword in CL_Rcon_f --- src/client/cl_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 0199a520..fa47988e 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -1786,7 +1786,7 @@ void CL_Rcon_f( void ) { char message[MAX_RCON_MESSAGE]; netadr_t to; - if ( !rcon_client_password->string ) { + if ( !rcon_client_password->string[0] ) { Com_Printf ("You must set 'rconpassword' before\n" "issuing an rcon command.\n"); return; -- cgit From 0bb0fb2bac331ce4d4a9756b7f62969a6278ee5b Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Mon, 28 Sep 2015 01:12:17 -0500 Subject: Remove unused define MAC_EVENT_PUMP_MSEC --- src/renderergl1/tr_backend.c | 2 -- src/renderergl2/tr_backend.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/renderergl1/tr_backend.c b/src/renderergl1/tr_backend.c index 18a033b6..7cd455e8 100644 --- a/src/renderergl1/tr_backend.c +++ b/src/renderergl1/tr_backend.c @@ -496,8 +496,6 @@ void RB_BeginDrawingView (void) { } -#define MAC_EVENT_PUMP_MSEC 5 - /* ================== RB_RenderDrawSurfList diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 6c03db3c..2a61e114 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -550,8 +550,6 @@ void RB_BeginDrawingView (void) { } -#define MAC_EVENT_PUMP_MSEC 5 - /* ================== RB_RenderDrawSurfList -- cgit From c65bd7998d56cae2670b30e84a2dbc547002d65d Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Wed, 30 Sep 2015 01:26:27 -0500 Subject: Maybe fix old MSYS when there is an empty for loop Based on ioquake3 svn r1485. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 408909f3..69c65534 100644 --- a/Makefile +++ b/Makefile @@ -1209,7 +1209,7 @@ endif NAKED_TARGETS=$(shell echo $(TARGETS) | sed -e "s!$(B)/!!g") -print_list=@for i in $(1); \ +print_list=-@for i in $(1); \ do \ echo " $$i"; \ done -- cgit From 2680cae42a9009628ded887d9470ed8abf45fc0f Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 16 Oct 2015 03:16:26 -0500 Subject: Add support for uncompressed image upload flag to OpenGL1 --- src/renderergl1/tr_image.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/renderergl1/tr_image.c b/src/renderergl1/tr_image.c index e3a1f2eb..2ed43ef0 100644 --- a/src/renderergl1/tr_image.c +++ b/src/renderergl1/tr_image.c @@ -558,6 +558,7 @@ static void Upload32( unsigned *data, qboolean mipmap, qboolean picmip, qboolean lightMap, + qboolean allowCompression, int *format, int *pUploadWidth, int *pUploadHeight ) { @@ -693,11 +694,11 @@ static void Upload32( unsigned *data, } else { - if ( glConfig.textureCompression == TC_S3TC_ARB ) + if ( allowCompression && glConfig.textureCompression == TC_S3TC_ARB ) { internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } - else if ( glConfig.textureCompression == TC_S3TC ) + else if ( allowCompression && glConfig.textureCompression == TC_S3TC ) { internalFormat = GL_RGB4_S3TC; } @@ -893,6 +894,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, image->flags & IMGFLAG_MIPMAP, image->flags & IMGFLAG_PICMIP, isLightmap, + !(image->flags & IMGFLAG_NO_COMPRESSION), &image->internalFormat, &image->uploadWidth, &image->uploadHeight ); -- cgit From 27b955ed8aae71e0a4a15d75e1c06ffa6516fbe5 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 16 Oct 2015 19:18:38 -0500 Subject: Fix not swapping buffers because out of cmd buffer space Reserve space for end of list and swap buffer commands. These are absolutely required and cannot be dropped. Dropping swap buffer command causes screen to not update and possible crash from drawsurf buffer overflow if not enough cmd buffer space for many continous frames. --- src/renderergl1/tr_cmds.c | 19 +++++++++++++++---- src/renderergl2/tr_cmds.c | 19 +++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/renderergl1/tr_cmds.c b/src/renderergl1/tr_cmds.c index 23aa9897..0ff7faee 100644 --- a/src/renderergl1/tr_cmds.c +++ b/src/renderergl1/tr_cmds.c @@ -115,19 +115,19 @@ void R_IssuePendingRenderCommands( void ) { /* ============ -R_GetCommandBuffer +R_GetCommandBufferReserved make sure there is enough command space ============ */ -void *R_GetCommandBuffer( int bytes ) { +void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) { renderCommandList_t *cmdList; cmdList = &backEndData->commands; bytes = PAD(bytes, sizeof(void *)); // always leave room for the end of list command - if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) { + if ( cmdList->used + bytes + 4 + reservedBytes > MAX_RENDER_COMMANDS ) { if ( bytes > MAX_RENDER_COMMANDS - 4 ) { ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes ); } @@ -140,6 +140,17 @@ void *R_GetCommandBuffer( int bytes ) { return cmdList->cmds + cmdList->used - bytes; } +/* +============= +R_GetCommandBuffer + +returns NULL if there is not enough space for important commands +============= +*/ +void *R_GetCommandBuffer( int bytes ) { + return R_GetCommandBufferReserved( bytes, sizeof ( swapBuffersCommand_t ) ); +} + /* ============= @@ -540,7 +551,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) { if ( !tr.registered ) { return; } - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); + cmd = R_GetCommandBufferReserved( sizeof( *cmd ), 0 ); if ( !cmd ) { return; } diff --git a/src/renderergl2/tr_cmds.c b/src/renderergl2/tr_cmds.c index 07fe146f..4599511b 100644 --- a/src/renderergl2/tr_cmds.c +++ b/src/renderergl2/tr_cmds.c @@ -122,19 +122,19 @@ void R_IssuePendingRenderCommands( void ) { /* ============ -R_GetCommandBuffer +R_GetCommandBufferReserved make sure there is enough command space ============ */ -void *R_GetCommandBuffer( int bytes ) { +void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) { renderCommandList_t *cmdList; cmdList = &backEndData->commands; bytes = PAD(bytes, sizeof(void *)); // always leave room for the end of list command - if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) { + if ( cmdList->used + bytes + 4 + reservedBytes > MAX_RENDER_COMMANDS ) { if ( bytes > MAX_RENDER_COMMANDS - 4 ) { ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes ); } @@ -147,6 +147,17 @@ void *R_GetCommandBuffer( int bytes ) { return cmdList->cmds + cmdList->used - bytes; } +/* +============= +R_GetCommandBuffer + +returns NULL if there is not enough space for important commands +============= +*/ +void *R_GetCommandBuffer( int bytes ) { + return R_GetCommandBufferReserved( bytes, sizeof ( swapBuffersCommand_t ) ); +} + /* ============= @@ -611,7 +622,7 @@ void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) { if ( !tr.registered ) { return; } - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); + cmd = R_GetCommandBufferReserved( sizeof( *cmd ), 0 ); if ( !cmd ) { return; } -- cgit From 0972dc8edfdadae375ab0a517e324178f8ec99f0 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 16 Oct 2015 20:12:51 -0500 Subject: Fix crash from reading past end of tr.refdef.drawSurfs The number of draw surfaces was range checked against number of surfaces for the current view but needs to check total for the frame otherwise can read past the end of the tr.refdef.drawSurfs array when there are multiple views. --- src/renderergl1/tr_main.c | 18 ++++++++++-------- src/renderergl2/tr_main.c | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/renderergl1/tr_main.c b/src/renderergl1/tr_main.c index b216d38f..7df28230 100644 --- a/src/renderergl1/tr_main.c +++ b/src/renderergl1/tr_main.c @@ -1147,13 +1147,6 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { return; } - // if we overflowed MAX_DRAWSURFS, the drawsurfs - // wrapped around in the buffer and we will be missing - // the first surfaces, not the last ones - if ( numDrawSurfs > MAX_DRAWSURFS ) { - numDrawSurfs = MAX_DRAWSURFS; - } - // sort the drawsurfs by sort type, then orientation, then shader R_RadixSort( drawSurfs, numDrawSurfs ); @@ -1362,6 +1355,7 @@ or a mirror / remote location */ void R_RenderView (viewParms_t *parms) { int firstDrawSurf; + int numDrawSurfs; if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { return; @@ -1384,7 +1378,15 @@ void R_RenderView (viewParms_t *parms) { R_GenerateDrawSurfs(); - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); + // if we overflowed MAX_DRAWSURFS, the drawsurfs + // wrapped around in the buffer and we will be missing + // the first surfaces, not the last ones + numDrawSurfs = tr.refdef.numDrawSurfs; + if ( numDrawSurfs > MAX_DRAWSURFS ) { + numDrawSurfs = MAX_DRAWSURFS; + } + + R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf ); // draw main system development information (surface outlines, etc) R_DebugGraphics(); diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index 287f95d3..2682d471 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -1821,13 +1821,6 @@ void R_SortDrawSurfs( drawSurf_t *drawSurfs, int numDrawSurfs ) { return; } - // if we overflowed MAX_DRAWSURFS, the drawsurfs - // wrapped around in the buffer and we will be missing - // the first surfaces, not the last ones - if ( numDrawSurfs > MAX_DRAWSURFS ) { - numDrawSurfs = MAX_DRAWSURFS; - } - // sort the drawsurfs by sort type, then orientation, then shader R_RadixSort( drawSurfs, numDrawSurfs ); @@ -2054,6 +2047,7 @@ or a mirror / remote location */ void R_RenderView (viewParms_t *parms) { int firstDrawSurf; + int numDrawSurfs; if ( parms->viewportWidth <= 0 || parms->viewportHeight <= 0 ) { return; @@ -2076,7 +2070,15 @@ void R_RenderView (viewParms_t *parms) { R_GenerateDrawSurfs(); - R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, tr.refdef.numDrawSurfs - firstDrawSurf ); + // if we overflowed MAX_DRAWSURFS, the drawsurfs + // wrapped around in the buffer and we will be missing + // the first surfaces, not the last ones + numDrawSurfs = tr.refdef.numDrawSurfs; + if ( numDrawSurfs > MAX_DRAWSURFS ) { + numDrawSurfs = MAX_DRAWSURFS; + } + + R_SortDrawSurfs( tr.refdef.drawSurfs + firstDrawSurf, numDrawSurfs - firstDrawSurf ); // draw main system development information (surface outlines, etc) R_DebugGraphics(); -- cgit From 6c232efd91fd288342bc6865a36fa1c8c0a23575 Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Fri, 16 Oct 2015 20:50:25 -0500 Subject: Fix reserved size for swap buffer command being too small on x86_64 --- src/renderergl1/tr_cmds.c | 2 +- src/renderergl2/tr_cmds.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderergl1/tr_cmds.c b/src/renderergl1/tr_cmds.c index 0ff7faee..58f199e3 100644 --- a/src/renderergl1/tr_cmds.c +++ b/src/renderergl1/tr_cmds.c @@ -148,7 +148,7 @@ returns NULL if there is not enough space for important commands ============= */ void *R_GetCommandBuffer( int bytes ) { - return R_GetCommandBufferReserved( bytes, sizeof ( swapBuffersCommand_t ) ); + return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) ); } diff --git a/src/renderergl2/tr_cmds.c b/src/renderergl2/tr_cmds.c index 4599511b..fe0ee82b 100644 --- a/src/renderergl2/tr_cmds.c +++ b/src/renderergl2/tr_cmds.c @@ -155,7 +155,7 @@ returns NULL if there is not enough space for important commands ============= */ void *R_GetCommandBuffer( int bytes ) { - return R_GetCommandBufferReserved( bytes, sizeof ( swapBuffersCommand_t ) ); + return R_GetCommandBufferReserved( bytes, PAD( sizeof( swapBuffersCommand_t ), sizeof(void *) ) ); } -- cgit From 802eb6dfaffb6efba11705fcce16eed8a6e34bad Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sat, 17 Oct 2015 21:57:16 -0500 Subject: Replace 4 with sizeof( int ) in R_GetCommandBufferReserved --- src/renderergl1/tr_cmds.c | 4 ++-- src/renderergl2/tr_cmds.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/renderergl1/tr_cmds.c b/src/renderergl1/tr_cmds.c index 58f199e3..d92a8b94 100644 --- a/src/renderergl1/tr_cmds.c +++ b/src/renderergl1/tr_cmds.c @@ -127,8 +127,8 @@ void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) { bytes = PAD(bytes, sizeof(void *)); // always leave room for the end of list command - if ( cmdList->used + bytes + 4 + reservedBytes > MAX_RENDER_COMMANDS ) { - if ( bytes > MAX_RENDER_COMMANDS - 4 ) { + if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) { + if ( bytes > MAX_RENDER_COMMANDS - sizeof( int ) ) { ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes ); } // if we run out of room, just start dropping commands diff --git a/src/renderergl2/tr_cmds.c b/src/renderergl2/tr_cmds.c index fe0ee82b..5d27c52d 100644 --- a/src/renderergl2/tr_cmds.c +++ b/src/renderergl2/tr_cmds.c @@ -134,8 +134,8 @@ void *R_GetCommandBufferReserved( int bytes, int reservedBytes ) { bytes = PAD(bytes, sizeof(void *)); // always leave room for the end of list command - if ( cmdList->used + bytes + 4 + reservedBytes > MAX_RENDER_COMMANDS ) { - if ( bytes > MAX_RENDER_COMMANDS - 4 ) { + if ( cmdList->used + bytes + sizeof( int ) + reservedBytes > MAX_RENDER_COMMANDS ) { + if ( bytes > MAX_RENDER_COMMANDS - sizeof( int ) ) { ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes ); } // if we run out of room, just start dropping commands -- cgit From 2bdf7e48b4eae30a1194887725e872c0c4053399 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 2 Dec 2015 17:08:40 -0800 Subject: OpenGL2: automatically load textures with a _s suffix as specular. --- src/renderergl2/tr_shader.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/renderergl2/tr_shader.c b/src/renderergl2/tr_shader.c index 68b5cb60..98e8776e 100644 --- a/src/renderergl2/tr_shader.c +++ b/src/renderergl2/tr_shader.c @@ -2213,12 +2213,33 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, if (r_specularMapping->integer) { + image_t *diffuseImg; if (specular) { //ri.Printf(PRINT_ALL, ", specularmap %s", specular->bundle[0].image[0]->imgName); diffuse->bundle[TB_SPECULARMAP] = specular->bundle[0]; VectorCopy4(specular->specularScale, diffuse->specularScale); } + else if ((lightmap || useLightVector || useLightVertex) && (diffuseImg = diffuse->bundle[TB_DIFFUSEMAP].image[0])) + { + char specularName[MAX_QPATH]; + image_t *specularImg; + imgFlags_t specularFlags = (diffuseImg->flags & ~(IMGFLAG_GENNORMALMAP | IMGFLAG_SRGB)) | IMGFLAG_NOLIGHTSCALE; + + COM_StripExtension(diffuseImg->imgName, specularName, MAX_QPATH); + Q_strcat(specularName, MAX_QPATH, "_s"); + + specularImg = R_FindImageFile(specularName, IMGTYPE_COLORALPHA, specularFlags); + + if (specularImg) + { + diffuse->bundle[TB_SPECULARMAP] = diffuse->bundle[0]; + diffuse->bundle[TB_SPECULARMAP].numImageAnimations = 0; + diffuse->bundle[TB_SPECULARMAP].image[0] = specularImg; + + VectorSet4(diffuse->specularScale, 1.0f, 1.0f, 1.0f, 1.0f); + } + } } if (tcgen || diffuse->bundle[0].numTexMods) -- cgit From e8a31f6a628ca309d1c5119d6d52c391e225445d Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 3 Dec 2015 02:44:33 -0800 Subject: OpenGL2: Remove some rendering options for simplicity. --- src/renderergl2/glsl/lightall_fp.glsl | 224 ++++++---------------------------- src/renderergl2/tr_glsl.c | 35 ------ src/renderergl2/tr_init.c | 2 - src/renderergl2/tr_local.h | 1 - 4 files changed, 35 insertions(+), 227 deletions(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index d1182781..c0d2bc80 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -150,156 +150,35 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) } #endif -vec3 CalcDiffuse(vec3 diffuseAlbedo, vec3 N, vec3 L, vec3 E, float NE, float NL, float shininess) +vec3 CalcDiffuse(vec3 diffuseAlbedo, float EH, float NH, float r) { - #if defined(USE_OREN_NAYAR) || defined(USE_TRIACE_OREN_NAYAR) - float gamma = dot(E, L) - NE * NL; - float B = 2.22222 + 0.1 * shininess; - - #if defined(USE_OREN_NAYAR) - float A = 1.0 - 1.0 / (2.0 + 0.33 * shininess); - gamma = clamp(gamma, 0.0, 1.0); - #endif - - #if defined(USE_TRIACE_OREN_NAYAR) - float A = 1.0 - 1.0 / (2.0 + 0.65 * shininess); - - if (gamma >= 0.0) - #endif - { - B = max(B * max(NL, NE), EPSILON); - } - - return diffuseAlbedo * (A + gamma / B); - #else - return diffuseAlbedo; - #endif -} - -vec3 EnvironmentBRDF(float gloss, float NE, vec3 specular) -{ - #if 1 - // from http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf - vec4 t = vec4( 1.0/0.96, 0.475, (0.0275 - 0.25 * 0.04)/0.96,0.25 ) * gloss; - t += vec4( 0.0, 0.0, (0.015 - 0.75 * 0.04)/0.96,0.75 ); - float a0 = t.x * min( t.y, exp2( -9.28 * NE ) ) + t.z; - float a1 = t.w; - return clamp( a0 + specular * ( a1 - a0 ), 0.0, 1.0 ); - #elif 0 - // from http://seblagarde.wordpress.com/2011/08/17/hello-world/ - return specular + CalcFresnel(NE) * clamp(vec3(gloss) - specular, 0.0, 1.0); - #else - // from http://advances.realtimerendering.com/s2011/Lazarov-Physically-Based-Lighting-in-Black-Ops%20%28Siggraph%202011%20Advances%20in%20Real-Time%20Rendering%20Course%29.pptx - return mix(specular.rgb, vec3(1.0), CalcFresnel(NE) / (4.0 - 3.0 * gloss)); - #endif -} - -float CalcBlinn(float NH, float shininess) -{ -#if defined(USE_BLINN) || defined(USE_BLINN_FRESNEL) - // Normalized Blinn-Phong - float norm = shininess * 0.125 + 1.0; -#elif defined(USE_MCAULEY) - // Cook-Torrance as done by Stephen McAuley - // http://blog.selfshadow.com/publications/s2012-shading-course/mcauley/s2012_pbs_farcry3_notes_v2.pdf - float norm = shininess * 0.25 + 0.125; -#elif defined(USE_GOTANDA) - // Neumann-Neumann as done by Yoshiharu Gotanda - // http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf - float norm = shininess * 0.124858 + 0.269182; -#elif defined(USE_LAZAROV) - // Cook-Torrance as done by Dimitar Lazarov - // http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf - float norm = shininess * 0.125 + 0.25; -#else - float norm = 1.0; -#endif - -#if 0 - // from http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/ - float a = shininess + 0.775; - return norm * exp(a * NH - a); -#else - return norm * pow(NH, shininess); -#endif -} - -float CalcGGX(float NH, float gloss) -{ - // from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf - float a_sq = exp2(gloss * -13.0 + 1.0); - float d = ((NH * NH) * (a_sq - 1.0) + 1.0); - return a_sq / (d * d); -} - -float CalcFresnel(float EH) -{ -#if 1 - // From http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf - // not accurate, but fast - return exp2(-10.0 * EH); -#elif 0 - // From http://seblagarde.wordpress.com/2012/06/03/spherical-gaussien-approximation-for-blinn-phong-phong-and-fresnel/ - return exp2((-5.55473 * EH - 6.98316) * EH); -#elif 0 - float blend = 1.0 - EH; - float blend2 = blend * blend; - blend *= blend2 * blend2; - - return blend; +#if defined(USE_BURLEY) + // modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf + float fd90 = -0.5 + EH * EH * r; + float burley = 1.0 + fd90 * 0.04 / NH; + burley *= burley; + return diffuseAlbedo * burley; #else - return pow(1.0 - EH, 5.0); + return diffuseAlbedo; #endif } -float CalcVisibility(float NH, float NL, float NE, float EH, float gloss) +vec3 EnvironmentBRDF(float r, float NE, vec3 specular) { -#if defined(USE_GOTANDA) - // Neumann-Neumann as done by Yoshiharu Gotanda - // http://research.tri-ace.com/Data/s2012_beyond_CourseNotes.pdf - return 1.0 / max(max(NL, NE), EPSILON); -#elif defined(USE_LAZAROV) - // Cook-Torrance as done by Dimitar Lazarov - // http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf - float k = min(1.0, gloss + 0.545); - return 1.0 / (k * (EH * EH - 1.0) + 1.0); -#elif defined(USE_GGX) - float roughness = exp2(gloss * -6.5); - - // Modified from http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf - // NL, NE in numerator factored out from cook-torrance - float k = roughness + 1.0; - k *= k * 0.125; - - float k2 = 1.0 - k; - - float invGeo1 = NL * k2 + k; - float invGeo2 = NE * k2 + k; - - return 1.0 / (invGeo1 * invGeo2); -#else - return 1.0; -#endif + // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf + float v = 1.0 - max(r, NE); + v *= v * v; + return vec3(v) + specular; } - -vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float gloss, float shininess) +vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float r) { -#if defined(USE_GGX) - float distrib = CalcGGX(NH, gloss); -#else - float distrib = CalcBlinn(NH, shininess); -#endif - -#if defined(USE_BLINN) - vec3 fSpecular = specular; -#else - vec3 fSpecular = mix(specular, vec3(1.0), CalcFresnel(EH)); -#endif - - float vis = CalcVisibility(NH, NL, NE, EH, gloss); - - return fSpecular * (distrib * vis); + // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf + float rr = r*r; + float rrrr = rr*rr; + float d = (NH * NH) * (rrrr - 1.0) + 1.0; + float v = (EH * EH) * (r + 0.5); + return specular * (rrrr / (4.0 * d * d * v)); } @@ -421,14 +300,7 @@ void main() shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0); #if defined(SHADOWMAP_MODULATE) - //vec3 shadowColor = min(u_PrimaryLightAmbient, lightColor); - vec3 shadowColor = u_PrimaryLightAmbient * lightColor; - - #if 0 - // Only shadow when the world light is parallel to the primary light - shadowValue = 1.0 + (shadowValue - 1.0) * clamp(dot(L, var_PrimaryLightDir.xyz), 0.0, 1.0); - #endif - lightColor = mix(shadowColor, lightColor, shadowValue); + lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r; #endif #endif @@ -465,65 +337,39 @@ void main() #if defined(r_materialGamma) diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma)); + #if !defined(SPECULAR_IS_METALLIC) specular.rgb = pow(specular.rgb, vec3(r_materialGamma)); + #endif #endif float gloss = specular.a; - float shininess = exp2(gloss * 13.0); + float r = exp2(-3.0 * gloss); #if defined(SPECULAR_IS_METALLIC) - // diffuse is actually base color, and red of specular is metallicness - float metallic = specular.r; + // diffuse is actually base color, and green of specular is metallicness + float metallic = specular.g; - specular.rgb = (0.96 * metallic) * diffuse.rgb + vec3(0.04); + specular.rgb = metallic * diffuse.rgb + vec3(0.04 - 0.04 * metallic); diffuse.rgb *= 1.0 - metallic; #else // adjust diffuse by specular reflectance, to maintain energy conservation diffuse.rgb *= vec3(1.0) - specular.rgb; #endif - reflectance = CalcDiffuse(diffuse.rgb, N, L, E, NE, NL, shininess); - - #if defined(r_deluxeSpecular) || defined(USE_LIGHT_VECTOR) - float adjGloss = gloss; - float adjShininess = shininess; - - #if !defined(USE_LIGHT_VECTOR) - adjGloss *= r_deluxeSpecular; - adjShininess = exp2(adjGloss * 13.0); - #endif - - H = normalize(L + E); - + reflectance = CalcDiffuse(diffuse.rgb, EH, NH, r); + #if defined(USE_SHADOWMAP) && defined(SHADOWMAP_MODULATE) + // bit of a hack, with modulated shadowmaps, add specular to sunlight + H = normalize(var_PrimaryLightDir.xyz + E); EH = clamp(dot(E, H), 0.0, 1.0); NH = clamp(dot(N, H), 0.0, 1.0); - - #if !defined(USE_LIGHT_VECTOR) - reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess) * r_deluxeSpecular; - #else - reflectance += CalcSpecular(specular.rgb, NH, NL, NE, EH, adjGloss, adjShininess); - #endif + reflectance += shadowValue * CalcSpecular(specular.rgb, NH, NL, NE, EH, r); #endif gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); - -#if 0 - vec3 aSpecular = EnvironmentBRDF(gloss, NE, specular.rgb); - - // do ambient as two hemisphere lights, one straight up one straight down - float hemiDiffuseUp = N.z * 0.5 + 0.5; - float hemiDiffuseDown = 1.0 - hemiDiffuseUp; - float hemiSpecularUp = mix(hemiDiffuseUp, float(N.z >= 0.0), gloss); - float hemiSpecularDown = 1.0 - hemiSpecularUp; - - gl_FragColor.rgb += ambientColor * 0.75 * (diffuse.rgb * hemiDiffuseUp + aSpecular * hemiSpecularUp); - gl_FragColor.rgb += ambientColor * 0.25 * (diffuse.rgb * hemiDiffuseDown + aSpecular * hemiSpecularDown); -#else gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb); -#endif #if defined(USE_CUBEMAP) - reflectance = EnvironmentBRDF(gloss, NE, specular.rgb); + reflectance = EnvironmentBRDF(r, NE, specular.rgb); vec3 R = reflect(E, N); @@ -565,8 +411,8 @@ void main() EH2 = clamp(dot(E, H2), 0.0, 1.0); NH2 = clamp(dot(N, H2), 0.0, 1.0); - reflectance = CalcDiffuse(diffuse.rgb, N, L2, E, NE, NL2, shininess); - reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, gloss, shininess); + reflectance = CalcDiffuse(diffuse.rgb, EH2, NH2, r); + reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, r); lightColor = u_PrimaryLightColor * var_Color.rgb; diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index f526b8c6..3fcb9350 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1022,9 +1022,6 @@ void GLSL_InitGPUShaders(void) extradefines[0] = '\0'; - if (r_deluxeSpecular->value > 0.000001f) - Q_strcat(extradefines, 1024, va("#define r_deluxeSpecular %f\n", r_deluxeSpecular->value)); - if (r_specularIsMetallic->value) Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n"); @@ -1067,12 +1064,6 @@ void GLSL_InitGPUShaders(void) { Q_strcat(extradefines, 1024, "#define USE_NORMALMAP\n"); - if (r_normalMapping->integer == 2) - Q_strcat(extradefines, 1024, "#define USE_OREN_NAYAR\n"); - - if (r_normalMapping->integer == 3) - Q_strcat(extradefines, 1024, "#define USE_TRIACE_OREN_NAYAR\n"); - #ifdef USE_VERT_TANGENT_SPACE Q_strcat(extradefines, 1024, "#define USE_VERT_TANGENT_SPACE\n"); attribs |= ATTR_TANGENT; @@ -1087,34 +1078,8 @@ void GLSL_InitGPUShaders(void) } if (r_specularMapping->integer) - { Q_strcat(extradefines, 1024, "#define USE_SPECULARMAP\n"); - switch (r_specularMapping->integer) - { - case 1: - default: - Q_strcat(extradefines, 1024, "#define USE_BLINN\n"); - break; - - case 2: - Q_strcat(extradefines, 1024, "#define USE_BLINN_FRESNEL\n"); - break; - - case 3: - Q_strcat(extradefines, 1024, "#define USE_MCAULEY\n"); - break; - - case 4: - Q_strcat(extradefines, 1024, "#define USE_GOTANDA\n"); - break; - - case 5: - Q_strcat(extradefines, 1024, "#define USE_LAZAROV\n"); - break; - } - } - if (r_cubeMapping->integer) Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n"); } diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index ea62249a..a5d4c465 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -141,7 +141,6 @@ cvar_t *r_specularMapping; cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; -cvar_t *r_deluxeSpecular; cvar_t *r_specularIsMetallic; cvar_t *r_baseNormalX; cvar_t *r_baseNormalY; @@ -1141,7 +1140,6 @@ void R_Register( void ) r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_deluxeSpecular = ri.Cvar_Get( "r_deluxeSpecular", "0.3", CVAR_ARCHIVE | CVAR_LATCH ); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 76cbe9c7..02d0887e 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1786,7 +1786,6 @@ extern cvar_t *r_specularMapping; extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; -extern cvar_t *r_deluxeSpecular; extern cvar_t *r_specularIsMetallic; extern cvar_t *r_baseNormalX; extern cvar_t *r_baseNormalY; -- cgit From 3372e9eaf5c21e1e44f000e09a94584231ba9550 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 8 Dec 2015 05:17:05 -0800 Subject: OpenGL2: Add option in code for alternate overbright method. --- src/renderergl2/tr_bsp.c | 10 ++++++++++ src/renderergl2/tr_image.c | 4 ++++ src/renderergl2/tr_local.h | 1 + src/renderergl2/tr_scene.c | 4 ++++ src/renderergl2/tr_shade.c | 23 ++++++++++++++++------- 5 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index beb07fe3..d1508051 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -102,7 +102,11 @@ static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) { int shift, r, g, b; // shift the color data based on overbright range +#if defined(USE_OVERBRIGHT) shift = r_mapOverBrightBits->integer - tr.overbrightBits; +#else + shift = 0; +#endif // shift the data based on overbright range r = in[0] << shift; @@ -137,7 +141,9 @@ static void R_ColorShiftLightingFloats(float in[4], float out[4], float scale ) { float r, g, b; +#if defined(USE_OVERBRIGHT) scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits); +#endif r = in[0] * scale; g = in[1] * scale; @@ -2756,7 +2762,11 @@ void R_LoadLightGrid( lump_t *l ) { if (hdrLightGrid) { +#if defined(USE_OVERBRIGHT) float lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits); +#else + float lightScale = 1.0f; +#endif //ri.Printf(PRINT_ALL, "found!\n"); diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index ef244d56..541b1a38 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -2856,7 +2856,11 @@ void R_SetColorMappings( void ) { int inf; // setup the overbright lighting +#if defined(USE_OVERBRIGHT) tr.overbrightBits = r_overBrightBits->integer; +#else + tr.overbrightBits = 0; +#endif // allow 2 overbright bits if ( tr.overbrightBits > 2 ) { diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 02d0887e..a38cf7fc 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -59,6 +59,7 @@ typedef unsigned int glIndex_t; #define CUBE_MAP_SIZE (1 << CUBE_MAP_MIPS) #define USE_VERT_TANGENT_SPACE +#define USE_OVERBRIGHT typedef struct dlight_s { vec3_t origin; diff --git a/src/renderergl2/tr_scene.c b/src/renderergl2/tr_scene.c index 51bb412e..94997a8c 100644 --- a/src/renderergl2/tr_scene.c +++ b/src/renderergl2/tr_scene.c @@ -350,7 +350,11 @@ void RE_BeginScene(const refdef_t *fd) } else { +#if defined(USE_OVERBRIGHT) float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); +#else + float scale = (1 << r_mapOverBrightBits->integer) / 255.0f; +#endif if (r_forceSun->integer) { VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol); diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index 9853313c..e7a73842 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -445,9 +445,22 @@ static void ProjectDlightTexture( void ) { static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor, int blend ) { + qboolean isBlend = ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR) + || ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR) + || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR) + || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); + + qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL); + +#if defined(USE_OVERBRIGHT) + float exactLight = 1.0f; +#else + float exactLight = (isBlend || !isWorldDraw) ? 1.0f : (float)(1 << r_mapOverBrightBits->integer); +#endif + baseColor[0] = baseColor[1] = - baseColor[2] = + baseColor[2] = exactLight; baseColor[3] = 1.0f; vertColor[0] = @@ -474,7 +487,7 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t vertColor[0] = vertColor[1] = - vertColor[2] = + vertColor[2] = exactLight; vertColor[3] = 1.0f; break; case CGEN_CONST: @@ -602,11 +615,7 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t } // multiply color by overbrightbits if this isn't a blend - if (tr.overbrightBits - && !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_DST_COLOR) - && !((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR) - && !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR) - && !((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR)) + if (tr.overbrightBits && !isBlend) { float scale = 1 << tr.overbrightBits; -- cgit From e3ac1437c4e4df764cc3279324fab7e3ee032e2a Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 8 Dec 2015 21:23:50 -0800 Subject: OpenGL2: Add r_glossIsRoughness. --- src/renderergl2/glsl/lightall_fp.glsl | 44 ++++++++++++++++++------------- src/renderergl2/tr_glsl.c | 3 +++ src/renderergl2/tr_init.c | 2 ++ src/renderergl2/tr_local.h | 1 + src/renderergl2/tr_shade.c | 3 +-- src/renderergl2/tr_shader.c | 49 ++++++++++++++++++++++++++++++----- 6 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index c0d2bc80..6c8977e1 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -150,11 +150,11 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) } #endif -vec3 CalcDiffuse(vec3 diffuseAlbedo, float EH, float NH, float r) +vec3 CalcDiffuse(vec3 diffuseAlbedo, float EH, float NH, float roughness) { #if defined(USE_BURLEY) // modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf - float fd90 = -0.5 + EH * EH * r; + float fd90 = -0.5 + EH * EH * roughness; float burley = 1.0 + fd90 * 0.04 / NH; burley *= burley; return diffuseAlbedo * burley; @@ -163,21 +163,21 @@ vec3 CalcDiffuse(vec3 diffuseAlbedo, float EH, float NH, float r) #endif } -vec3 EnvironmentBRDF(float r, float NE, vec3 specular) +vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular) { // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf - float v = 1.0 - max(r, NE); + float v = 1.0 - max(roughness, NE); v *= v * v; return vec3(v) + specular; } -vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float r) +vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float roughness) { // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf - float rr = r*r; + float rr = roughness*roughness; float rrrr = rr*rr; float d = (NH * NH) * (rrrr - 1.0) + 1.0; - float v = (EH * EH) * (r + 0.5); + float v = (EH * EH) * (roughness + 0.5); return specular * (rrrr / (4.0 * d * d * v)); } @@ -276,6 +276,11 @@ void main() attenuation = 1.0; #endif + #if defined(r_lightGamma) + lightColor = pow(lightColor, vec3(r_lightGamma)); + ambientColor = pow(ambientColor, vec3(r_lightGamma)); + #endif + #if defined(USE_NORMALMAP) #if defined(SWIZZLE_NORMALMAP) N.xy = texture2D(u_NormalMap, texCoords).ag - vec2(0.5); @@ -304,11 +309,6 @@ void main() #endif #endif - #if defined(r_lightGamma) - lightColor = pow(lightColor, vec3(r_lightGamma)); - ambientColor = pow(ambientColor, vec3(r_lightGamma)); - #endif - #if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX) ambientColor = lightColor; float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0); @@ -343,7 +343,11 @@ void main() #endif float gloss = specular.a; - float r = exp2(-3.0 * gloss); + #if defined(GLOSS_IS_ROUGHNESS) + float roughness = gloss; + #else + float roughness = exp2(-3.0 * gloss); + #endif #if defined(SPECULAR_IS_METALLIC) // diffuse is actually base color, and green of specular is metallicness @@ -356,20 +360,20 @@ void main() diffuse.rgb *= vec3(1.0) - specular.rgb; #endif - reflectance = CalcDiffuse(diffuse.rgb, EH, NH, r); + reflectance = CalcDiffuse(diffuse.rgb, EH, NH, roughness); #if defined(USE_SHADOWMAP) && defined(SHADOWMAP_MODULATE) // bit of a hack, with modulated shadowmaps, add specular to sunlight H = normalize(var_PrimaryLightDir.xyz + E); EH = clamp(dot(E, H), 0.0, 1.0); NH = clamp(dot(N, H), 0.0, 1.0); - reflectance += shadowValue * CalcSpecular(specular.rgb, NH, NL, NE, EH, r); + reflectance += shadowValue * CalcSpecular(specular.rgb, NH, NL, NE, EH, roughness); #endif gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb); #if defined(USE_CUBEMAP) - reflectance = EnvironmentBRDF(r, NE, specular.rgb); + reflectance = EnvironmentBRDF(roughness, NE, specular.rgb); vec3 R = reflect(E, N); @@ -377,7 +381,11 @@ void main() // from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir; + #if defined(GLOSS_IS_ROUGHNESS) + vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, roughness).rgb * u_EnableTextures.w; + #else vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w; + #endif // normalize cubemap based on lowest mip (~diffuse) // multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation @@ -411,8 +419,8 @@ void main() EH2 = clamp(dot(E, H2), 0.0, 1.0); NH2 = clamp(dot(N, H2), 0.0, 1.0); - reflectance = CalcDiffuse(diffuse.rgb, EH2, NH2, r); - reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, r); + reflectance = CalcDiffuse(diffuse.rgb, EH2, NH2, roughness); + reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, roughness); lightColor = u_PrimaryLightColor * var_Color.rgb; diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index 3fcb9350..8ce3a4e7 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1025,6 +1025,9 @@ void GLSL_InitGPUShaders(void) if (r_specularIsMetallic->value) Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n"); + if (r_glossIsRoughness->value) + Q_strcat(extradefines, 1024, "#define GLOSS_IS_ROUGHNESS\n"); + if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index a5d4c465..2828270e 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -142,6 +142,7 @@ cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; cvar_t *r_specularIsMetallic; +cvar_t *r_glossIsRoughness; cvar_t *r_baseNormalX; cvar_t *r_baseNormalY; cvar_t *r_baseParallax; @@ -1141,6 +1142,7 @@ void R_Register( void ) r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index a38cf7fc..f69aec19 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1788,6 +1788,7 @@ extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; extern cvar_t *r_specularIsMetallic; +extern cvar_t *r_glossIsRoughness; extern cvar_t *r_baseNormalX; extern cvar_t *r_baseNormalY; extern cvar_t *r_baseParallax; diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index e7a73842..f0a6d34b 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -450,11 +450,10 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR) || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); - qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL); - #if defined(USE_OVERBRIGHT) float exactLight = 1.0f; #else + qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL); float exactLight = (isBlend || !isWorldDraw) ? 1.0f : (float)(1 << r_mapOverBrightBits->integer); #endif diff --git a/src/renderergl2/tr_shader.c b/src/renderergl2/tr_shader.c index 98e8776e..b4a120ca 100644 --- a/src/renderergl2/tr_shader.c +++ b/src/renderergl2/tr_shader.c @@ -955,17 +955,23 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) exponent = atof( token ); - // Change shininess to gloss - // FIXME: assumes max exponent of 8192 and min of 1, must change here if altered in lightall_fp.glsl - exponent = CLAMP(exponent, 1.0, 8192.0); - - stage->specularScale[3] = log(exponent) / log(8192.0); + if (r_glossIsRoughness->integer) + stage->specularScale[3] = powf(2.0f / (exponent + 2.0), 0.25); + else + { + // Change shininess to gloss + // Assumes max exponent of 8190 and min of 0, must change here if altered in lightall_fp.glsl + exponent = CLAMP(exponent, 0.0f, 8190.0f); + stage->specularScale[3] = (log2f(exponent + 2.0f) - 1.0f) / 12.0f; + } } // // gloss // else if (!Q_stricmp(token, "gloss")) { + float gloss; + token = COM_ParseExt(text, qfalse); if ( token[0] == 0 ) { @@ -973,7 +979,38 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) continue; } - stage->specularScale[3] = atof( token ); + gloss = atof(token); + + if (r_glossIsRoughness->integer) + stage->specularScale[3] = exp2f(-3.0f * gloss); + else + stage->specularScale[3] = gloss; + } + // + // roughness + // + else if (!Q_stricmp(token, "roughness")) + { + float roughness; + + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) + { + ri.Printf(PRINT_WARNING, "WARNING: missing parameter for roughness in shader '%s'\n", shader.name); + continue; + } + + roughness = atof(token); + + if (r_glossIsRoughness->integer) + stage->specularScale[3] = roughness; + else + { + if (roughness >= 0.125) + stage->specularScale[3] = log2f(1.0f / roughness) / 3.0f; + else + stage->specularScale[3] = 1.0f; + } } // // parallaxDepth -- cgit From 6f6ca6d529e1739565dbc64891fa7f1b478b8460 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 9 Dec 2015 02:00:40 -0800 Subject: OpenGL2: Parse radius entries from misc_cubemap entities. --- src/renderergl2/tr_backend.c | 9 ++++++--- src/renderergl2/tr_bsp.c | 20 +++++++++++++------- src/renderergl2/tr_light.c | 2 +- src/renderergl2/tr_local.h | 9 +++++++-- src/renderergl2/tr_main.c | 2 +- src/renderergl2/tr_shade.c | 9 ++++----- 6 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 2a61e114..ad43e5b2 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -483,8 +483,9 @@ void RB_BeginDrawingView (void) { // FIXME: hack for cubemap testing if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) { + cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; //qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0); - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]->texnum, 0); + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, cubemap->image->texnum, 0); } } } @@ -1312,9 +1313,11 @@ const void *RB_DrawSurfs( const void *data ) { if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) { + cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; + FBO_Bind(NULL); GL_SelectTexture(TB_CUBEMAP); - GL_BindToTMU(tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex], TB_CUBEMAP); + GL_BindToTMU(cubemap->image, TB_CUBEMAP); qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); GL_SelectTexture(0); } @@ -1725,7 +1728,7 @@ const void *RB_PostProcess(const void *data) { VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256); //FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); - FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1], NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); + FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); } } #endif diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index d1508051..d2a5f5f2 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -2997,16 +2997,17 @@ void R_LoadCubemapEntities(char *cubemapEntityName) return; tr.numCubemaps = numCubemaps; - tr.cubemapOrigins = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemapOrigins), h_low); - tr.cubemaps = ri.Hunk_Alloc( tr.numCubemaps * sizeof(*tr.cubemaps), h_low); + tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); + memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps)); numCubemaps = 0; while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars)) { int i; qboolean isCubemap = qfalse; - qboolean positionSet = qfalse; + qboolean originSet = qfalse; vec3_t origin; + float parallaxRadius = 1000.0f; for (i = 0; i < numSpawnVars; i++) { @@ -3016,14 +3017,19 @@ void R_LoadCubemapEntities(char *cubemapEntityName) if (!Q_stricmp(spawnVars[i][0], "origin")) { sscanf(spawnVars[i][1], "%f %f %f", &origin[0], &origin[1], &origin[2]); - positionSet = qtrue; + originSet = qtrue; + } + else if (!Q_stricmp(spawnVars[i][0], "radius")) + { + sscanf(spawnVars[i][1], "%f", ¶llaxRadius); } } - if (isCubemap && positionSet) + if (isCubemap && originSet) { //ri.Printf(PRINT_ALL, "cubemap at %f %f %f\n", origin[0], origin[1], origin[2]); - VectorCopy(origin, tr.cubemapOrigins[numCubemaps]); + VectorCopy(origin, tr.cubemaps[numCubemaps].origin); + tr.cubemaps[numCubemaps].parallaxRadius = parallaxRadius; numCubemaps++; } } @@ -3069,7 +3075,7 @@ void R_RenderAllCubemaps(void) for (i = 0; i < tr.numCubemaps; i++) { - tr.cubemaps[i] = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); + tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); } for (i = 0; i < tr.numCubemaps; i++) diff --git a/src/renderergl2/tr_light.c b/src/renderergl2/tr_light.c index 317f4585..7c661dd5 100644 --- a/src/renderergl2/tr_light.c +++ b/src/renderergl2/tr_light.c @@ -472,7 +472,7 @@ int R_CubemapForPoint( vec3_t point ) vec3_t diff; vec_t length; - VectorSubtract(point, tr.cubemapOrigins[i], diff); + VectorSubtract(point, tr.cubemaps[i].origin, diff); length = DotProduct(diff, diff); if (shortest > length) diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index f69aec19..73681f32 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -61,6 +61,12 @@ typedef unsigned int glIndex_t; #define USE_VERT_TANGENT_SPACE #define USE_OVERBRIGHT +typedef struct cubemap_s { + vec3_t origin; + float parallaxRadius; + image_t *image; +} cubemap_t; + typedef struct dlight_s { vec3_t origin; vec3_t color; // range from 0.0 to 1.0, should be color normalized @@ -1561,8 +1567,7 @@ typedef struct { int fatLightmapStep; int numCubemaps; - vec3_t *cubemapOrigins; - image_t **cubemaps; + cubemap_t *cubemaps; trRefEntity_t *currentEntity; trRefEntity_t worldEntity; // point currentEntity at this when rendering world diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index 2682d471..14d18755 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -2863,7 +2863,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) memset( &refdef, 0, sizeof( refdef ) ); refdef.rdflags = 0; - VectorCopy(tr.cubemapOrigins[cubemapIndex], refdef.vieworg); + VectorCopy(tr.cubemaps[cubemapIndex].origin, refdef.vieworg); switch(cubemapSide) { diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index f0a6d34b..04b62517 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -1376,15 +1376,14 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer) { vec4_t vec; + cubemap_t *cubemap = &tr.cubemaps[input->cubemapIndex - 1]; - GL_BindToTMU( tr.cubemaps[input->cubemapIndex - 1], TB_CUBEMAP); + GL_BindToTMU( cubemap->image, TB_CUBEMAP); - vec[0] = tr.cubemapOrigins[input->cubemapIndex - 1][0] - backEnd.viewParms.or.origin[0]; - vec[1] = tr.cubemapOrigins[input->cubemapIndex - 1][1] - backEnd.viewParms.or.origin[1]; - vec[2] = tr.cubemapOrigins[input->cubemapIndex - 1][2] - backEnd.viewParms.or.origin[2]; + VectorSubtract(cubemap->origin, backEnd.viewParms.or.origin, vec); vec[3] = 1.0f; - VectorScale4(vec, 1.0f / 1000.0f, vec); + VectorScale4(vec, 1.0f / cubemap->parallaxRadius, vec); GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec); } -- cgit From c9cf340a4eb8d81b44e8c02b167b9ab6319167fd Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 9 Dec 2015 03:42:12 -0800 Subject: OpenGL2: Forgot a multiply. --- src/renderergl2/glsl/lightall_fp.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index 6c8977e1..9330b1f8 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -382,7 +382,7 @@ void main() vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir; #if defined(GLOSS_IS_ROUGHNESS) - vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, roughness).rgb * u_EnableTextures.w; + vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 * roughness).rgb * u_EnableTextures.w; #else vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w; #endif -- cgit From 9cdedf11eff894db8f9f572ab52eae37fdacf473 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 9 Dec 2015 05:25:58 -0800 Subject: OpenGL2: Use correct sunlight color for sunlight specular. --- src/renderergl2/glsl/lightall_fp.glsl | 19 ++++++++----------- src/renderergl2/tr_scene.c | 25 ++++++++++--------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index 9330b1f8..17dc9fca 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -361,13 +361,6 @@ void main() #endif reflectance = CalcDiffuse(diffuse.rgb, EH, NH, roughness); - #if defined(USE_SHADOWMAP) && defined(SHADOWMAP_MODULATE) - // bit of a hack, with modulated shadowmaps, add specular to sunlight - H = normalize(var_PrimaryLightDir.xyz + E); - EH = clamp(dot(E, H), 0.0, 1.0); - NH = clamp(dot(N, H), 0.0, 1.0); - reflectance += shadowValue * CalcSpecular(specular.rgb, NH, NL, NE, EH, roughness); - #endif gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb); @@ -403,7 +396,7 @@ void main() gl_FragColor.rgb += cubeLightColor * reflectance; #endif - #if defined(USE_PRIMARY_LIGHT) + #if defined(USE_PRIMARY_LIGHT) || defined(SHADOWMAP_MODULATE) vec3 L2, H2; float NL2, EH2, NH2; @@ -419,10 +412,14 @@ void main() EH2 = clamp(dot(E, H2), 0.0, 1.0); NH2 = clamp(dot(N, H2), 0.0, 1.0); - reflectance = CalcDiffuse(diffuse.rgb, EH2, NH2, roughness); - reflectance += CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, roughness); + reflectance = CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, roughness); + + // bit of a hack, with modulated shadowmaps, ignore diffuse + #if !defined(SHADOWMAP_MODULATE) + reflectance += CalcDiffuse(diffuse.rgb, EH2, NH2, roughness); + #endif - lightColor = u_PrimaryLightColor * var_Color.rgb; + lightColor = u_PrimaryLightColor; #if defined(r_lightGamma) lightColor = pow(lightColor, vec3(r_lightGamma)); diff --git a/src/renderergl2/tr_scene.c b/src/renderergl2/tr_scene.c index 94997a8c..7e326a88 100644 --- a/src/renderergl2/tr_scene.c +++ b/src/renderergl2/tr_scene.c @@ -336,35 +336,30 @@ void RE_BeginScene(const refdef_t *fd) } else { +#if defined(USE_OVERBRIGHT) + float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); +#else + float scale = (1 << r_mapOverBrightBits->integer) / 255.0f; +#endif tr.refdef.colorScale = r_forceSun->integer ? r_forceSunMapLightScale->value : tr.mapLightScale; + if (r_forceSun->integer) + VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol); + else + VectorScale(tr.sunLight, scale, tr.refdef.sunCol); + if (r_sunlightMode->integer == 1) { - tr.refdef.sunCol[0] = - tr.refdef.sunCol[1] = - tr.refdef.sunCol[2] = 1.0f; - tr.refdef.sunAmbCol[0] = tr.refdef.sunAmbCol[1] = tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale; } else { -#if defined(USE_OVERBRIGHT) - float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); -#else - float scale = (1 << r_mapOverBrightBits->integer) / 255.0f; -#endif if (r_forceSun->integer) - { - VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol); VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol); - } else - { - VectorScale(tr.sunLight, scale, tr.refdef.sunCol); VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol); - } } } -- cgit From f77b9694e3d2870f62b27589c70c2cf254248db3 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 15 Dec 2015 03:23:55 -0800 Subject: OpenGL2: Switch to RGTC from LATC for normal maps. Also added a RGTC compressor as a workaround on Intel graphics. --- src/renderercommon/qgl.h | 12 +- src/renderergl2/tr_extensions.c | 26 ++++- src/renderergl2/tr_glsl.c | 2 +- src/renderergl2/tr_image.c | 248 ++++++++++++++++++++++++---------------- src/renderergl2/tr_local.h | 4 +- 5 files changed, 179 insertions(+), 113 deletions(-) diff --git a/src/renderercommon/qgl.h b/src/renderercommon/qgl.h index 559c4387..cc0dd6a7 100644 --- a/src/renderercommon/qgl.h +++ b/src/renderercommon/qgl.h @@ -928,12 +928,12 @@ extern void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLs #define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 #endif -#ifndef GL_EXT_texture_compression_latc -#define GL_EXT_texture_compression_latc -#define GL_COMPRESSED_LUMINANCE_LATC1_EXT 0x8C70 -#define GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT 0x8C71 -#define GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT 0x8C72 -#define GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT 0x8C73 +#ifndef GL_ARB_texture_compression_rgtc +#define GL_ARB_texture_compression_rgtc +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE #endif #ifndef GL_ARB_texture_compression_bptc diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c index 811b8377..2c1407b2 100644 --- a/src/renderergl2/tr_extensions.c +++ b/src/renderergl2/tr_extensions.c @@ -585,6 +585,22 @@ void GLimp_InitExtraExtensions() ri.Printf(PRINT_ALL, result[2], extension); } + // GL_ARB_texture_compression + extension = "GL_ARB_texture_compression"; + glRefConfig.arbTextureCompression = qfalse; + if (GLimp_HaveExtension(extension)) + { + qglCompressedTexImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage3DARB"); + qglCompressedTexImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage2DARB"); + qglCompressedTexImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexImage1DARB"); + qglCompressedTexSubImage3DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage3DARB"); + qglCompressedTexSubImage2DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage2DARB"); + qglCompressedTexSubImage1DARB = (void *)SDL_GL_GetProcAddress("glCompressedTexSubImage1DARB"); + qglGetCompressedTexImageARB = (void *)SDL_GL_GetProcAddress("glGetCompressedTexImageARB"); + glRefConfig.arbTextureCompression = qtrue; + ri.Printf(PRINT_ALL, result[glRefConfig.arbTextureCompression], extension); + } + // GL_EXT_framebuffer_multisample extension = "GL_EXT_framebuffer_multisample"; glRefConfig.framebufferMultisample = qfalse; @@ -601,12 +617,12 @@ void GLimp_InitExtraExtensions() glRefConfig.textureCompression = TCR_NONE; - // GL_EXT_texture_compression_latc - extension = "GL_EXT_texture_compression_latc"; + // GL_ARB_texture_compression_rgtc + extension = "GL_ARB_texture_compression_rgtc"; if (GLimp_HaveExtension(extension)) { - if (r_ext_compressed_textures->integer) - glRefConfig.textureCompression |= TCR_LATC; + if (r_ext_compressed_textures->integer && glRefConfig.arbTextureCompression) + glRefConfig.textureCompression |= TCR_RGTC; ri.Printf(PRINT_ALL, result[r_ext_compressed_textures->integer ? 1 : 0], extension); } @@ -615,6 +631,8 @@ void GLimp_InitExtraExtensions() ri.Printf(PRINT_ALL, result[2], extension); } + glRefConfig.swizzleNormalmap = r_ext_compressed_textures->integer && !(glRefConfig.textureCompression & TCR_RGTC); + // GL_ARB_texture_compression_bptc extension = "GL_ARB_texture_compression_bptc"; if (GLimp_HaveExtension(extension)) diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index 8ce3a4e7..14e20105 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1031,7 +1031,7 @@ void GLSL_InitGPUShaders(void) if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); - if (1) + if (glRefConfig.swizzleNormalmap) Q_strcat(extradefines, 1024, "#define SWIZZLE_NORMALMAP\n"); if (r_hdr->integer && !glRefConfig.floatLightmap) diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 541b1a38..93ee28e9 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -177,15 +177,20 @@ void R_ImageList_f( void ) { format = "sBPTC"; // 128 bits per 16 pixels, so 1 byte per pixel break; - case GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT: - format = "LATC "; + case GL_COMPRESSED_RG_RGTC2: + format = "RGTC2"; // 128 bits per 16 pixels, so 1 byte per pixel break; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: format = "DXT1 "; // 64 bits per 16 pixels, so 4 bits per pixel estSize /= 2; break; + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + format = "DXT1a"; + // 64 bits per 16 pixels, so 4 bits per pixel + estSize /= 2; + break; case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: format = "DXT5 "; // 128 bits per 16 pixels, so 1 byte per pixel @@ -1332,41 +1337,6 @@ static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) } -static void R_MipMapLuminanceAlpha (const byte *in, byte *out, int width, int height) -{ - int i, j, row; - - if ( width == 1 && height == 1 ) { - return; - } - - row = width * 4; - width >>= 1; - height >>= 1; - - if ( width == 0 || height == 0 ) { - width += height; // get largest - for (i=0 ; i> 1; - out[3] = (in[3] + in[7]) >> 1; - } - return; - } - - for (i=0 ; i> 2; - out[3] = (in[3] + in[7] + in[row+3] + in[row+7]) >> 2; - } - } - -} - - static void R_MipMapNormalHeight (const byte *in, byte *out, int width, int height, qboolean swizzle) { int i, j; @@ -1657,13 +1627,13 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light if(normalmap) { - if ((!RawImage_HasAlpha(data, numPixels) || (type == IMGTYPE_NORMAL)) && !forceNoCompression && (glRefConfig.textureCompression & TCR_LATC)) - { - internalFormat = GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT; - } - else + if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels)) { - if ( !forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB ) + if (!forceNoCompression && glRefConfig.textureCompression & TCR_BPTC) + { + internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + } + else if (!forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB) { internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; } @@ -1680,6 +1650,33 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light internalFormat = GL_RGBA; } } + else + { + if (!forceNoCompression && glRefConfig.textureCompression & TCR_RGTC) + { + internalFormat = GL_COMPRESSED_RG_RGTC2; + } + else if (!forceNoCompression && glRefConfig.textureCompression & TCR_BPTC) + { + internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + } + else if (!forceNoCompression && glConfig.textureCompression == TC_S3TC_ARB) + { + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } + else if (r_texturebits->integer == 16) + { + internalFormat = GL_RGB5; + } + else if (r_texturebits->integer == 32) + { + internalFormat = GL_RGB8; + } + else + { + internalFormat = GL_RGB; + } + } } else if(lightMap) { @@ -1775,10 +1772,101 @@ static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean light return internalFormat; } +static void CompressMonoBlock(byte outdata[8], const byte indata[16]) +{ + int hi, lo, diff, bias, outbyte, shift, i; + byte *p = outdata; + + hi = lo = indata[0]; + for (i = 1; i < 16; i++) + { + hi = MAX(indata[i], hi); + lo = MIN(indata[i], lo); + } + + *p++ = hi; + *p++ = lo; + + diff = hi - lo; + + if (diff == 0) + { + outbyte = (hi == 255) ? 255 : 0; + + for (i = 0; i < 6; i++) + *p++ = outbyte; + + return; + } + + bias = diff / 2 - lo * 7; + outbyte = shift = 0; + for (i = 0; i < 16; i++) + { + const byte fixIndex[8] = { 1, 7, 6, 5, 4, 3, 2, 0 }; + byte index = fixIndex[(indata[i] * 7 + bias) / diff]; + + outbyte |= index << shift; + shift += 3; + if (shift >= 8) + { + *p++ = outbyte & 0xff; + shift -= 8; + outbyte >>= 8; + } + } +} + +static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int mip) +{ + int wBlocks, hBlocks, y, x, size; + byte *compressedData, *p; + + wBlocks = (width + 3) / 4; + hBlocks = (height + 3) / 4; + size = wBlocks * hBlocks * 16; + + p = compressedData = ri.Hunk_AllocateTempMemory(size); + for (y = 0; y < height; y += 4) + { + int oh = MIN(4, height - y); + + for (x = 0; x < width; x += 4) + { + byte workingData[16]; + int component; + + int ow = MIN(4, width - x); + + for (component = 0; component < 2; component++) + { + int ox, oy; + + for (oy = 0; oy < oh; oy++) + for (ox = 0; ox < ow; ox++) + workingData[oy * 4 + ox] = data[((y + oy) * width + x + ox) * 4 + component]; + + // dupe data to fill + for (oy = 0; oy < 4; oy++) + for (ox = (oy < oh) ? ow : 0; ox < 4; ox++) + workingData[oy * 4 + ox] = workingData[(oy % oh) * 4 + ox % ow]; + + CompressMonoBlock(p, workingData); + p += 8; + } + } + } + + qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData); + + ri.Hunk_FreeTempMemory(compressedData); +} + static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) { int dataFormat, dataType; + qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); switch(internalFormat) { @@ -1802,7 +1890,12 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei if ( subtexture ) qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); else - qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data ); + { + if (rgtc) + RawImage_UploadToRgtc2Texture(data, width, height, 0); + else + qglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data); + } if (flags & IMGFLAG_MIPMAP) { @@ -1815,14 +1908,7 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei { if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) { - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { @@ -1849,7 +1935,10 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei } else { - qglTexImage2D (GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data ); + if (rgtc) + RawImage_UploadToRgtc2Texture(data, width, height, miplevel); + else + qglTexImage2D(GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); } } } @@ -1903,25 +1992,11 @@ static void Upload32( byte *data, int width, int height, imgType_t type, imgFlag } } - // normals are always swizzled - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) + if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)) { RawImage_SwizzleRA(data, width, height); } - // LATC2 is only used for normals - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - byte *in = data; - int c = width * height; - while (c--) - { - in[0] = in[1]; - in[2] = in[1]; - in += 4; - } - } - // copy or resample data as appropriate for first MIP level if ( ( scaled_width == width ) && ( scaled_height == height ) ) { @@ -1943,14 +2018,7 @@ static void Upload32( byte *data, int width, int height, imgType_t type, imgFlag if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) { - if (internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { @@ -2186,26 +2254,11 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h int scaled_width, scaled_height, scaled_x, scaled_y; byte *data = pic; - // normals are always swizzled - if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) + if (glRefConfig.swizzleNormalmap && (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT)) { RawImage_SwizzleRA(pic, width, height); } - // LATC2 is only used for normals - if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - byte *in = data; - int c = width * height; - while (c--) - { - in[0] = in[1]; - in[2] = in[1]; - in += 4; - } - } - - RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer); scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); @@ -2238,14 +2291,7 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) { - if (image->internalFormat == GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT) - { - R_MipMapLuminanceAlpha( data, data, width, height ); - } - else - { - R_MipMapNormalHeight( data, data, width, height, qtrue); - } + R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); } else { diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 73681f32..0a1dc5fe 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1381,7 +1381,7 @@ typedef enum { typedef enum { TCR_NONE = 0x0000, - TCR_LATC = 0x0001, + TCR_RGTC = 0x0001, TCR_BPTC = 0x0002, } textureCompressionRef_t; @@ -1405,7 +1405,9 @@ typedef struct { qboolean textureFloat; qboolean halfFloatPixel; qboolean packedDepthStencil; + qboolean arbTextureCompression; textureCompressionRef_t textureCompression; + qboolean swizzleNormalmap; qboolean framebufferMultisample; qboolean framebufferBlit; -- cgit From fad434534de2f0794f84d6d1c13d8ed171b6a3e1 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 16 Dec 2015 07:12:30 -0800 Subject: OpenGL2: Some tr_image.c cleanup. --- src/renderergl2/tr_image.c | 301 ++++++++++++--------------------------------- 1 file changed, 77 insertions(+), 224 deletions(-) diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 93ee28e9..7047a0d6 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -1452,7 +1452,7 @@ RawImage_ScaleToPower2 =============== */ -static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_height, int *inout_scaled_width, int *inout_scaled_height, imgType_t type, imgFlags_t flags, byte **resampledBuffer) +static qboolean RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_height, imgType_t type, imgFlags_t flags, byte **resampledBuffer) { int width = *inout_width; int height = *inout_height; @@ -1461,6 +1461,7 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he qboolean picmip = flags & IMGFLAG_PICMIP; qboolean mipmap = flags & IMGFLAG_MIPMAP; qboolean clampToEdge = flags & IMGFLAG_CLAMPTOEDGE; + qboolean notScaled; // // convert to exact power of 2 sizes @@ -1507,22 +1508,9 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he *resampledBuffer = ri.Hunk_AllocateTempMemory( finalwidth * finalheight * 4 ); if (scaled_width != width || scaled_height != height) - { ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height); - } else - { - byte *inbyte, *outbyte; - int i; - - inbyte = *data; - outbyte = *resampledBuffer; - - for (i = width * height * 4; i > 0; i--) - { - *outbyte++ = *inbyte++; - } - } + Com_Memcpy(*resampledBuffer, *data, width * height * 4); if (type == IMGTYPE_COLORALPHA) RGBAtoYCoCgA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); @@ -1536,34 +1524,29 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he } if (type == IMGTYPE_COLORALPHA) - { YCoCgAtoRGBA(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); - } else if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { FillInNormalizedZ(*resampledBuffer, *resampledBuffer, scaled_width, scaled_height); - } - //endTime = ri.Milliseconds(); //ri.Printf(PRINT_ALL, "upsampled %dx%d to %dx%d in %dms\n", width, height, scaled_width, scaled_height, endTime - startTime); *data = *resampledBuffer; - width = scaled_width; - height = scaled_height; } - else if ( scaled_width != width || scaled_height != height ) { + else if ( scaled_width != width || scaled_height != height ) + { if (data && resampledBuffer) { *resampledBuffer = ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height); *data = *resampledBuffer; } - width = scaled_width; - height = scaled_height; } + width = scaled_width; + height = scaled_height; + // // perform optional picmip operation // @@ -1572,16 +1555,6 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he scaled_height >>= r_picmip->integer; } - // - // clamp to minimum size - // - if (scaled_width < 1) { - scaled_width = 1; - } - if (scaled_height < 1) { - scaled_height = 1; - } - // // clamp to the current upper OpenGL limit // scale both axis down equally so we don't have to @@ -1593,10 +1566,35 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he scaled_height >>= 1; } - *inout_width = width; - *inout_height = height; - *inout_scaled_width = scaled_width; - *inout_scaled_height = scaled_height; + // + // clamp to minimum size + // + scaled_width = MAX(1, scaled_width); + scaled_height = MAX(1, scaled_height); + + notScaled = (width == scaled_width) && (height == scaled_height); + + // + // rescale texture to new size using existing mipmap functions + // + if (data) + { + while (width > scaled_width || height > scaled_height) + { + if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) + R_MipMapNormalHeight(*data, *data, width, height, qfalse); + else + R_MipMapsRGB(*data, width, height); + + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + } + } + + *inout_width = width; + *inout_height = height; + + return notScaled; } @@ -1951,23 +1949,30 @@ Upload32 =============== */ -static void Upload32( byte *data, int width, int height, imgType_t type, imgFlags_t flags, - qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight) +static void Upload32(byte *data, int x, int y, int width, int height, image_t *image) { - byte *scaledBuffer = NULL; byte *resampledBuffer = NULL; - int scaled_width, scaled_height; int i, c; byte *scan; - RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, type, flags, &resampledBuffer); + imgType_t type = image->type; + imgFlags_t flags = image->flags; + GLenum internalFormat = image->internalFormat; + qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height); + qboolean notScaled = qtrue; + qboolean mipmap = !!(flags & IMGFLAG_MIPMAP); - scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); + if (!data) + { + RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL); + RawImage_UploadTexture(NULL, 0, 0, width, height, internalFormat, type, flags, qfalse); + goto done; + } + else if (!subtexture) + { + notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer); + } - // - // scan the texture for each channel's max values - // and verify if the alpha channel is being used or not - // c = width*height; scan = data; @@ -1993,100 +1998,28 @@ static void Upload32( byte *data, int width, int height, imgType_t type, imgFlag } if (glRefConfig.swizzleNormalmap && (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)) - { RawImage_SwizzleRA(data, width, height); - } - // copy or resample data as appropriate for first MIP level - if ( ( scaled_width == width ) && - ( scaled_height == height ) ) { - if (!(flags & IMGFLAG_MIPMAP)) - { - RawImage_UploadTexture( data, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse ); - //qglTexImage2D (GL_TEXTURE_2D, 0, internalFormat, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; + // This corresponds to what the OpenGL1 renderer does + if (!(flags & IMGFLAG_NOLIGHTSCALE) && (!notScaled || mipmap)) + R_LightScaleTexture(data, width, height, !mipmap); - goto done; - } - Com_Memcpy (scaledBuffer, data, width*height*4); - } - else + if (subtexture) { - // use the normal mip-mapping function to go down from here - while ( width > scaled_width || height > scaled_height ) { - - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { - R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); - } - else - { - R_MipMapsRGB( data, width, height ); - } - - width >>= 1; - height >>= 1; - if ( width < 1 ) { - width = 1; - } - if ( height < 1 ) { - height = 1; - } - } - Com_Memcpy( scaledBuffer, data, width * height * 4 ); + // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped + RawImage_UploadTexture(data, x, y, width, height, internalFormat, type, flags, qtrue); + GL_CheckErrors(); + return; } - if (!(flags & IMGFLAG_NOLIGHTSCALE)) - R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(flags & IMGFLAG_MIPMAP) ); - - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; - - RawImage_UploadTexture(scaledBuffer, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(data, 0, 0, width, height, internalFormat, type, flags, qfalse); done: - if (flags & IMGFLAG_MIPMAP) - { - if ( glConfig.textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp( 1, glConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) ); + image->uploadWidth = width; + image->uploadHeight = height; - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); - } - else - { - if ( glConfig.textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); - - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - - GL_CheckErrors(); - - if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); - if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); -} - - -static void EmptyTexture( int width, int height, imgType_t type, imgFlags_t flags, - qboolean lightMap, GLenum internalFormat, int *pUploadWidth, int *pUploadHeight ) -{ - int scaled_width, scaled_height; - - RawImage_ScaleToPower2(NULL, &width, &height, &scaled_width, &scaled_height, type, flags, NULL); - - *pUploadWidth = scaled_width; - *pUploadHeight = scaled_height; - - RawImage_UploadTexture(NULL, 0, 0, scaled_width, scaled_height, internalFormat, type, flags, qfalse); - - if (flags & IMGFLAG_MIPMAP) + if (mipmap) { if ( glConfig.textureFilterAnisotropic ) qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, @@ -2121,6 +2054,9 @@ static void EmptyTexture( int width, int height, imgType_t type, imgFlags_t flag } GL_CheckErrors(); + + if ( resampledBuffer != NULL ) + ri.Hunk_FreeTempMemory( resampledBuffer ); } @@ -2186,9 +2122,10 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT GL_SelectTexture( image->TMU ); } + GL_Bind(image); + if (image->flags & IMGFLAG_CUBEMAP) { - GL_Bind(image); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); @@ -2219,20 +2156,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT } else { - GL_Bind(image); - - if (pic) - { - Upload32( pic, image->width, image->height, image->type, image->flags, - isLightmap, image->internalFormat, &image->uploadWidth, - &image->uploadHeight ); - } - else - { - EmptyTexture(image->width, image->height, image->type, image->flags, - isLightmap, image->internalFormat, &image->uploadWidth, - &image->uploadHeight ); - } + Upload32( pic, 0, 0, image->width, image->height, image ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); @@ -2249,86 +2173,15 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ) { - byte *scaledBuffer = NULL; - byte *resampledBuffer = NULL; - int scaled_width, scaled_height, scaled_x, scaled_y; - byte *data = pic; - - if (glRefConfig.swizzleNormalmap && (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT)) - { - RawImage_SwizzleRA(pic, width, height); + if (qglActiveTextureARB) { + GL_SelectTexture(image->TMU); } - RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer); + GL_Bind(image); - scaledBuffer = ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); + Upload32(pic, x, y, width, height, image); - if ( qglActiveTextureARB ) { - GL_SelectTexture( image->TMU ); - } - - GL_Bind(image); - - // copy or resample data as appropriate for first MIP level - if ( ( scaled_width == width ) && - ( scaled_height == height ) ) { - if (!(image->flags & IMGFLAG_MIPMAP)) - { - scaled_x = x * scaled_width / width; - scaled_y = y * scaled_height / height; - RawImage_UploadTexture( data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue ); - //qglTexSubImage2D( GL_TEXTURE_2D, 0, scaled_x, scaled_y, scaled_width, scaled_height, GL_RGBA, GL_UNSIGNED_BYTE, data ); - - GL_CheckErrors(); - goto done; - } - Com_Memcpy (scaledBuffer, data, width*height*4); - } - else - { - // use the normal mip-mapping function to go down from here - while ( width > scaled_width || height > scaled_height ) { - - if (image->type == IMGTYPE_NORMAL || image->type == IMGTYPE_NORMALHEIGHT) - { - R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); - } - else - { - R_MipMapsRGB( data, width, height ); - } - - width >>= 1; - height >>= 1; - x >>= 1; - y >>= 1; - if ( width < 1 ) { - width = 1; - } - if ( height < 1 ) { - height = 1; - } - } - Com_Memcpy( scaledBuffer, data, width * height * 4 ); - } - - if (!(image->flags & IMGFLAG_NOLIGHTSCALE)) - R_LightScaleTexture (scaledBuffer, scaled_width, scaled_height, !(image->flags & IMGFLAG_MIPMAP) ); - - scaled_x = x * scaled_width / width; - scaled_y = y * scaled_height / height; - RawImage_UploadTexture( (byte *)data, scaled_x, scaled_y, scaled_width, scaled_height, image->internalFormat, image->type, image->flags, qtrue ); - -done: - - GL_SelectTexture( 0 ); - - GL_CheckErrors(); - - if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); - if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); + GL_SelectTexture(0); } //=================================================================== -- cgit From 342a3bd68085cdc11f3167253492043459ee9910 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 18 Dec 2015 06:53:20 -0800 Subject: OpenGL2: DDS (compressed textures) support. --- Makefile | 1 + src/renderergl2/tr_image.c | 130 ++++++++++-- src/renderergl2/tr_image_dds.c | 448 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 564 insertions(+), 15 deletions(-) create mode 100644 src/renderergl2/tr_image_dds.c diff --git a/Makefile b/Makefile index 69c65534..c1a5b29e 100644 --- a/Makefile +++ b/Makefile @@ -1558,6 +1558,7 @@ Q3R2OBJ = \ $(B)/renderergl2/tr_image_pcx.o \ $(B)/renderergl2/tr_image_png.o \ $(B)/renderergl2/tr_image_tga.o \ + $(B)/renderergl2/tr_image_dds.o \ $(B)/renderergl2/tr_init.o \ $(B)/renderergl2/tr_light.o \ $(B)/renderergl2/tr_main.o \ diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 7047a0d6..c35af4c2 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -1616,13 +1616,16 @@ static qboolean RawImage_HasAlpha(const byte *scan, int numPixels) return qfalse; } -static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags) +static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picFormat, qboolean lightMap, imgType_t type, imgFlags_t flags) { int samples = 3; GLenum internalFormat = GL_RGB; qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION); qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT); + if (picFormat != GL_RGBA8) + return picFormat; + if(normalmap) { if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels)) @@ -1861,11 +1864,67 @@ static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int } -static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) +static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) { int dataFormat, dataType; qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); + if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) + { + int bytesPer4x4Block = 0; + int miplevel = 0; + + switch (picFormat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + bytesPer4x4Block = 8; + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: + case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: + bytesPer4x4Block = 16; + break; + default: + ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat); + return; + break; + } + + for (miplevel = 0; miplevel < numMips; miplevel++) + { + int size; + + size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; + + if (subtexture) + qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data); + else + qglCompressedTexImage2DARB(GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, size, data); + + x >>= 1; + y >>= 1; + x -= x % 4; + y -= y % 4; + + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + data += size; + } + + return; + } + switch(internalFormat) { case GL_DEPTH_COMPONENT: @@ -1949,7 +2008,7 @@ Upload32 =============== */ -static void Upload32(byte *data, int x, int y, int width, int height, image_t *image) +static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image) { byte *resampledBuffer = NULL; int i, c; @@ -1965,11 +2024,16 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i if (!data) { RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL); - RawImage_UploadTexture(NULL, 0, 0, width, height, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); goto done; } else if (!subtexture) { + if (picFormat != GL_RGBA8) + { + RawImage_UploadTexture(data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); + goto done; + } notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer); } @@ -2007,12 +2071,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i if (subtexture) { // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped - RawImage_UploadTexture(data, x, y, width, height, internalFormat, type, flags, qtrue); + RawImage_UploadTexture(data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue); GL_CheckErrors(); return; } - RawImage_UploadTexture(data, 0, 0, width, height, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); done: @@ -2062,12 +2126,12 @@ done: /* ================ -R_CreateImage +R_CreateImage2 This is the only way any image_t are created ================ */ -image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) { +image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat ) { image_t *image; qboolean isLightmap = qfalse; long hash; @@ -2105,7 +2169,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT if (image->flags & IMGFLAG_CUBEMAP) internalFormat = GL_RGBA8; else - internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags); + internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags); } image->internalFormat = internalFormat; @@ -2156,7 +2220,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT } else { - Upload32( pic, 0, 0, image->width, image->height, image ); + Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); @@ -2171,6 +2235,20 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT return image; } + +/* +================ +R_CreateImage + +Wrapper for R_CreateImage2(), for the old parameters. +================ +*/ +image_t *R_CreateImage(const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat) +{ + return R_CreateImage2(name, pic, width, height, GL_RGBA8, 0, type, flags, internalFormat); +} + + void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ) { if (qglActiveTextureARB) { @@ -2179,13 +2257,16 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h GL_Bind(image); - Upload32(pic, x, y, width, height, image); + Upload32(pic, x, y, width, height, GL_RGBA8, 0, image); GL_SelectTexture(0); } //=================================================================== +// Prototype for dds loader function which isn't common to both renderers +void R_LoadDDS(const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips); + typedef struct { char *ext; @@ -2214,7 +2295,7 @@ Loads any of the supported image types into a cannonical 32 bit format. ================= */ -void R_LoadImage( const char *name, byte **pic, int *width, int *height ) +void R_LoadImage( const char *name, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips ) { qboolean orgNameFailed = qfalse; int orgLoader = -1; @@ -2226,11 +2307,28 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height ) *pic = NULL; *width = 0; *height = 0; + *picFormat = GL_RGBA8; + *numMips = 0; Q_strncpyz( localName, name, MAX_QPATH ); ext = COM_GetExtension( localName ); + // If compressed textures are enabled, try loading a DDS first, it'll load fastest + if (r_ext_compressed_textures->integer) + { + char ddsName[MAX_QPATH]; + + COM_StripExtension(name, ddsName, MAX_QPATH); + Q_strcat(ddsName, MAX_QPATH, ".dds"); + + R_LoadDDS(ddsName, pic, width, height, picFormat, numMips); + + // If loaded, we're done. + if (*pic) + return; + } + if( *ext ) { // Look for the correct loader and use it @@ -2302,6 +2400,8 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) image_t *image; int width, height; byte *pic; + GLenum picFormat; + int picNumMips; long hash; if (!name) { @@ -2328,12 +2428,12 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) // // load the pic from disk // - R_LoadImage( name, &pic, &width, &height ); + R_LoadImage( name, &pic, &width, &height, &picFormat, &picNumMips ); if ( pic == NULL ) { return NULL; } - if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) + if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) { char normalName[MAX_QPATH]; image_t *normalImage; @@ -2436,7 +2536,7 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) } } - image = R_CreateImage( ( char * ) name, pic, width, height, type, flags, 0 ); + image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0 ); ri.Free( pic ); return image; } diff --git a/src/renderergl2/tr_image_dds.c b/src/renderergl2/tr_image_dds.c new file mode 100644 index 00000000..578b3eda --- /dev/null +++ b/src/renderergl2/tr_image_dds.c @@ -0,0 +1,448 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + 2015 James Canete + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code is distributed in the hope that it will be +useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Quake III Arena source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ + +#include "../renderercommon/tr_common.h" + +typedef unsigned int ui32_t; + +typedef struct ddsHeader_s +{ + ui32_t headerSize; + ui32_t flags; + ui32_t height; + ui32_t width; + ui32_t pitchOrFirstMipSize; + ui32_t volumeDepth; + ui32_t numMips; + ui32_t reserved1[11]; + ui32_t always_0x00000020; + ui32_t pixelFormatFlags; + ui32_t fourCC; + ui32_t rgbBitCount; + ui32_t rBitMask; + ui32_t gBitMask; + ui32_t bBitMask; + ui32_t aBitMask; + ui32_t caps; + ui32_t caps2; + ui32_t caps3; + ui32_t caps4; + ui32_t reserved2; +} +ddsHeader_t; + +// flags: +#define _DDSFLAGS_REQUIRED 0x001007 +#define _DDSFLAGS_PITCH 0x8 +#define _DDSFLAGS_MIPMAPCOUNT 0x20000 +#define _DDSFLAGS_FIRSTMIPSIZE 0x80000 +#define _DDSFLAGS_VOLUMEDEPTH 0x800000 + +// pixelFormatFlags: +#define DDSPF_ALPHAPIXELS 0x1 +#define DDSPF_ALPHA 0x2 +#define DDSPF_FOURCC 0x4 +#define DDSPF_RGB 0x40 +#define DDSPF_YUV 0x200 +#define DDSPF_LUMINANCE 0x20000 + +// caps: +#define DDSCAPS_COMPLEX 0x8 +#define DDSCAPS_MIPMAP 0x400000 +#define DDSCAPS_REQUIRED 0x1000 + +// caps2: +#define DDSCAPS2_CUBEMAP 0xFE00 +#define DDSCAPS2_VOLUME 0x200000 + +typedef struct ddsHeaderDxt10_s +{ + ui32_t dxgiFormat; + ui32_t dimensions; + ui32_t miscFlags; + ui32_t arraySize; + ui32_t miscFlags2; +} +ddsHeaderDxt10_t; + +// dxgiFormat +// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx +typedef enum DXGI_FORMAT { + DXGI_FORMAT_UNKNOWN = 0, + DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, + DXGI_FORMAT_R32G32B32A32_FLOAT = 2, + DXGI_FORMAT_R32G32B32A32_UINT = 3, + DXGI_FORMAT_R32G32B32A32_SINT = 4, + DXGI_FORMAT_R32G32B32_TYPELESS = 5, + DXGI_FORMAT_R32G32B32_FLOAT = 6, + DXGI_FORMAT_R32G32B32_UINT = 7, + DXGI_FORMAT_R32G32B32_SINT = 8, + DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, + DXGI_FORMAT_R16G16B16A16_FLOAT = 10, + DXGI_FORMAT_R16G16B16A16_UNORM = 11, + DXGI_FORMAT_R16G16B16A16_UINT = 12, + DXGI_FORMAT_R16G16B16A16_SNORM = 13, + DXGI_FORMAT_R16G16B16A16_SINT = 14, + DXGI_FORMAT_R32G32_TYPELESS = 15, + DXGI_FORMAT_R32G32_FLOAT = 16, + DXGI_FORMAT_R32G32_UINT = 17, + DXGI_FORMAT_R32G32_SINT = 18, + DXGI_FORMAT_R32G8X24_TYPELESS = 19, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, + DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, + DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, + DXGI_FORMAT_R10G10B10A2_UNORM = 24, + DXGI_FORMAT_R10G10B10A2_UINT = 25, + DXGI_FORMAT_R11G11B10_FLOAT = 26, + DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, + DXGI_FORMAT_R8G8B8A8_UNORM = 28, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, + DXGI_FORMAT_R8G8B8A8_UINT = 30, + DXGI_FORMAT_R8G8B8A8_SNORM = 31, + DXGI_FORMAT_R8G8B8A8_SINT = 32, + DXGI_FORMAT_R16G16_TYPELESS = 33, + DXGI_FORMAT_R16G16_FLOAT = 34, + DXGI_FORMAT_R16G16_UNORM = 35, + DXGI_FORMAT_R16G16_UINT = 36, + DXGI_FORMAT_R16G16_SNORM = 37, + DXGI_FORMAT_R16G16_SINT = 38, + DXGI_FORMAT_R32_TYPELESS = 39, + DXGI_FORMAT_D32_FLOAT = 40, + DXGI_FORMAT_R32_FLOAT = 41, + DXGI_FORMAT_R32_UINT = 42, + DXGI_FORMAT_R32_SINT = 43, + DXGI_FORMAT_R24G8_TYPELESS = 44, + DXGI_FORMAT_D24_UNORM_S8_UINT = 45, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, + DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, + DXGI_FORMAT_R8G8_TYPELESS = 48, + DXGI_FORMAT_R8G8_UNORM = 49, + DXGI_FORMAT_R8G8_UINT = 50, + DXGI_FORMAT_R8G8_SNORM = 51, + DXGI_FORMAT_R8G8_SINT = 52, + DXGI_FORMAT_R16_TYPELESS = 53, + DXGI_FORMAT_R16_FLOAT = 54, + DXGI_FORMAT_D16_UNORM = 55, + DXGI_FORMAT_R16_UNORM = 56, + DXGI_FORMAT_R16_UINT = 57, + DXGI_FORMAT_R16_SNORM = 58, + DXGI_FORMAT_R16_SINT = 59, + DXGI_FORMAT_R8_TYPELESS = 60, + DXGI_FORMAT_R8_UNORM = 61, + DXGI_FORMAT_R8_UINT = 62, + DXGI_FORMAT_R8_SNORM = 63, + DXGI_FORMAT_R8_SINT = 64, + DXGI_FORMAT_A8_UNORM = 65, + DXGI_FORMAT_R1_UNORM = 66, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, + DXGI_FORMAT_R8G8_B8G8_UNORM = 68, + DXGI_FORMAT_G8R8_G8B8_UNORM = 69, + DXGI_FORMAT_BC1_TYPELESS = 70, + DXGI_FORMAT_BC1_UNORM = 71, + DXGI_FORMAT_BC1_UNORM_SRGB = 72, + DXGI_FORMAT_BC2_TYPELESS = 73, + DXGI_FORMAT_BC2_UNORM = 74, + DXGI_FORMAT_BC2_UNORM_SRGB = 75, + DXGI_FORMAT_BC3_TYPELESS = 76, + DXGI_FORMAT_BC3_UNORM = 77, + DXGI_FORMAT_BC3_UNORM_SRGB = 78, + DXGI_FORMAT_BC4_TYPELESS = 79, + DXGI_FORMAT_BC4_UNORM = 80, + DXGI_FORMAT_BC4_SNORM = 81, + DXGI_FORMAT_BC5_TYPELESS = 82, + DXGI_FORMAT_BC5_UNORM = 83, + DXGI_FORMAT_BC5_SNORM = 84, + DXGI_FORMAT_B5G6R5_UNORM = 85, + DXGI_FORMAT_B5G5R5A1_UNORM = 86, + DXGI_FORMAT_B8G8R8A8_UNORM = 87, + DXGI_FORMAT_B8G8R8X8_UNORM = 88, + DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, + DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, + DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, + DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, + DXGI_FORMAT_BC6H_TYPELESS = 94, + DXGI_FORMAT_BC6H_UF16 = 95, + DXGI_FORMAT_BC6H_SF16 = 96, + DXGI_FORMAT_BC7_TYPELESS = 97, + DXGI_FORMAT_BC7_UNORM = 98, + DXGI_FORMAT_BC7_UNORM_SRGB = 99, + DXGI_FORMAT_AYUV = 100, + DXGI_FORMAT_Y410 = 101, + DXGI_FORMAT_Y416 = 102, + DXGI_FORMAT_NV12 = 103, + DXGI_FORMAT_P010 = 104, + DXGI_FORMAT_P016 = 105, + DXGI_FORMAT_420_OPAQUE = 106, + DXGI_FORMAT_YUY2 = 107, + DXGI_FORMAT_Y210 = 108, + DXGI_FORMAT_Y216 = 109, + DXGI_FORMAT_NV11 = 110, + DXGI_FORMAT_AI44 = 111, + DXGI_FORMAT_IA44 = 112, + DXGI_FORMAT_P8 = 113, + DXGI_FORMAT_A8P8 = 114, + DXGI_FORMAT_B4G4R4A4_UNORM = 115, + DXGI_FORMAT_FORCE_UINT = 0xffffffffUL +} DXGI_FORMAT; + +#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \ + (((ui32_t)((x)[1])) << 8 ) | \ + (((ui32_t)((x)[2])) << 16) | \ + (((ui32_t)((x)[3])) << 24) ) + + +void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips ) +{ + union { + byte *b; + void *v; + } buffer; + int len; + ddsHeader_t *ddsHeader = NULL; + ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL; + byte *data; + + if (!picFormat) + { + ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!"); + return; + } + + if (width) + *width = 0; + if (height) + *height = 0; + if (picFormat) + *picFormat = GL_RGBA8; + if (numMips) + *numMips = 1; + + *pic = NULL; + + // + // load the file + // + len = ri.FS_ReadFile( ( char * ) filename, &buffer.v); + if (!buffer.b || len < 0) { + return; + } + + // + // reject files that are too small to hold even a header + // + if (len < 4 + sizeof(*ddsHeader)) + { + ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + // + // reject files that don't start with "DDS " + // + if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS ")) + { + ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + // + // parse header and dx10 header if available + // + ddsHeader = (ddsHeader_t *)(buffer.b + 4); + if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10")) + { + if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10)) + { + ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t)); + data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10); + len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10); + } + else + { + data = buffer.b + 4 + sizeof(*ddsHeader); + len -= 4 + sizeof(*ddsHeader); + } + + *width = ddsHeader->width; + *height = ddsHeader->height; + + if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT) + *numMips = ddsHeader->numMips; + else + *numMips = 1; + + // FIXME: handle cube map + //if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP) + + // + // Convert DXGI format/FourCC into OpenGL format + // + if (ddsHeaderDxt10) + { + switch (ddsHeaderDxt10->dxgiFormat) + { + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + // FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + break; + + case DXGI_FORMAT_BC1_UNORM_SRGB: + // FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT + *picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT; + break; + + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + break; + + case DXGI_FORMAT_BC2_UNORM_SRGB: + *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + break; + + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + break; + + case DXGI_FORMAT_BC3_UNORM_SRGB: + *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + break; + + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + *picFormat = GL_COMPRESSED_RED_RGTC1; + break; + + case DXGI_FORMAT_BC4_SNORM: + *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1; + break; + + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + *picFormat = GL_COMPRESSED_RG_RGTC2; + break; + + case DXGI_FORMAT_BC5_SNORM: + *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2; + break; + + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + *picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB; + break; + + case DXGI_FORMAT_BC6H_SF16: + *picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB; + break; + + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + *picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB; + break; + + case DXGI_FORMAT_BC7_UNORM_SRGB: + *picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + *picFormat = GL_SRGB8_ALPHA8_EXT; + break; + + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_SNORM: + *picFormat = GL_RGBA8; + break; + + default: + ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat); + ri.FS_FreeFile(buffer.v); + return; + break; + } + } + else + { + if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC) + { + if (ddsHeader->fourCC == EncodeFourCC("DXT1")) + *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + else if (ddsHeader->fourCC == EncodeFourCC("DXT2")) + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + else if (ddsHeader->fourCC == EncodeFourCC("DXT3")) + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + else if (ddsHeader->fourCC == EncodeFourCC("DXT4")) + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + else if (ddsHeader->fourCC == EncodeFourCC("DXT5")) + *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + else if (ddsHeader->fourCC == EncodeFourCC("ATI1")) + *picFormat = GL_COMPRESSED_RED_RGTC1; + else if (ddsHeader->fourCC == EncodeFourCC("BC4U")) + *picFormat = GL_COMPRESSED_RED_RGTC1; + else if (ddsHeader->fourCC == EncodeFourCC("BC4S")) + *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1; + else if (ddsHeader->fourCC == EncodeFourCC("ATI2")) + *picFormat = GL_COMPRESSED_RG_RGTC2; + else if (ddsHeader->fourCC == EncodeFourCC("BC5U")) + *picFormat = GL_COMPRESSED_RG_RGTC2; + else if (ddsHeader->fourCC == EncodeFourCC("BC5S")) + *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2; + else + { + ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename); + ri.FS_FreeFile(buffer.v); + return; + } + } + else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS) + && ddsHeader->rgbBitCount == 32 + && ddsHeader->rBitMask == 0x000000ff + && ddsHeader->gBitMask == 0x0000ff00 + && ddsHeader->bBitMask == 0x00ff0000 + && ddsHeader->aBitMask == 0xff000000) + { + *picFormat = GL_RGBA8; + } + else + { + ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename); + ri.FS_FreeFile(buffer.v); + return; + } + } + + *pic = ri.Malloc(len); + Com_Memcpy(*pic, data, len); + + ri.FS_FreeFile(buffer.v); +} -- cgit From ab9a49f87ddd323ce1958d0834ddbb7cab199f12 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 18 Dec 2015 19:42:15 -0800 Subject: OpenGL2: Add null dereference checks to DDS loader. --- src/renderergl2/tr_image_dds.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/renderergl2/tr_image_dds.c b/src/renderergl2/tr_image_dds.c index 578b3eda..8ad406fd 100644 --- a/src/renderergl2/tr_image_dds.c +++ b/src/renderergl2/tr_image_dds.c @@ -292,13 +292,18 @@ void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLen len -= 4 + sizeof(*ddsHeader); } - *width = ddsHeader->width; - *height = ddsHeader->height; + if (width) + *width = ddsHeader->width; + if (height) + *height = ddsHeader->height; - if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT) - *numMips = ddsHeader->numMips; - else - *numMips = 1; + if (numMips) + { + if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT) + *numMips = ddsHeader->numMips; + else + *numMips = 1; + } // FIXME: handle cube map //if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP) -- cgit From 674b8eeefffd56bf2454c08a4ba21682788dc3af Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Sun, 20 Dec 2015 03:08:50 -0800 Subject: Make jpeg loading errors non-fatal. --- src/renderercommon/tr_image_jpg.c | 43 +++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/renderercommon/tr_image_jpg.c b/src/renderercommon/tr_image_jpg.c index 2bbcb365..15c280d5 100644 --- a/src/renderercommon/tr_image_jpg.c +++ b/src/renderercommon/tr_image_jpg.c @@ -21,6 +21,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ +#include + #include "tr_common.h" /* @@ -43,16 +45,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # endif #endif -static void __attribute__((__noreturn__)) R_JPGErrorExit(j_common_ptr cinfo) +/* Catching errors, as done in libjpeg's example.c */ +typedef struct q_jpeg_error_mgr_s +{ + struct jpeg_error_mgr pub; /* "public" fields */ + + jmp_buf setjmp_buffer; /* for return to caller */ +} q_jpeg_error_mgr_t; + +static void R_JPGErrorExit(j_common_ptr cinfo) { char buffer[JMSG_LENGTH_MAX]; + + /* cinfo->err really points to a q_jpeg_error_mgr_s struct, so coerce pointer */ + q_jpeg_error_mgr_t *jerr = (q_jpeg_error_mgr_t *)cinfo->err; (*cinfo->err->format_message) (cinfo, buffer); - - /* Let the memory manager delete any temp files before we die */ - jpeg_destroy(cinfo); - - ri.Error(ERR_FATAL, "%s", buffer); + + ri.Printf(PRINT_ALL, "R_LoadJPG() error: %s", buffer); + + /* Return control to the setjmp point */ + longjmp(jerr->setjmp_buffer, 1); } static void R_JPGOutputMessage(j_common_ptr cinfo) @@ -84,7 +97,7 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh * Note that this struct must live as long as the main JPEG parameter * struct, to avoid dangling-pointer problems. */ - struct jpeg_error_mgr jerr; + q_jpeg_error_mgr_t jerr; /* More stuff */ JSAMPARRAY buffer; /* Output row buffer */ unsigned int row_stride; /* physical row width in output buffer */ @@ -116,10 +129,24 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh * This routine fills in the contents of struct jerr, and returns jerr's * address which we place into the link field in cinfo. */ - cinfo.err = jpeg_std_error(&jerr); + cinfo.err = jpeg_std_error(&jerr.pub); cinfo.err->error_exit = R_JPGErrorExit; cinfo.err->output_message = R_JPGOutputMessage; + /* Establish the setjmp return context for R_JPGErrorExit to use. */ + if (setjmp(jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object, close the input file, and return. + */ + jpeg_destroy_decompress(&cinfo); + ri.FS_FreeFile(fbuffer.v); + + /* Append the filename to the error for easier debugging */ + ri.Printf(PRINT_ALL, ", file %s\n", filename); + return; + } + /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); -- cgit From 5e21024a3ce91664273d61f26de679e6a5e9a213 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 21 Dec 2015 01:05:55 -0800 Subject: Fix error handling in RE_SaveJPGToBuffer(). --- src/renderercommon/tr_image_jpg.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/renderercommon/tr_image_jpg.c b/src/renderercommon/tr_image_jpg.c index 15c280d5..3e369c20 100644 --- a/src/renderercommon/tr_image_jpg.c +++ b/src/renderercommon/tr_image_jpg.c @@ -62,7 +62,7 @@ static void R_JPGErrorExit(j_common_ptr cinfo) (*cinfo->err->format_message) (cinfo, buffer); - ri.Printf(PRINT_ALL, "R_LoadJPG() error: %s", buffer); + ri.Printf(PRINT_ALL, "Error: %s", buffer); /* Return control to the setjmp point */ longjmp(jerr->setjmp_buffer, 1); @@ -143,7 +143,7 @@ void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *heigh ri.FS_FreeFile(fbuffer.v); /* Append the filename to the error for easier debugging */ - ri.Printf(PRINT_ALL, ", file %s\n", filename); + ri.Printf(PRINT_ALL, ", loading file %s\n", filename); return; } @@ -389,17 +389,29 @@ size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality, int image_width, int image_height, byte *image_buffer, int padding) { struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; + q_jpeg_error_mgr_t jerr; JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ my_dest_ptr dest; int row_stride; /* physical row width in image buffer */ size_t outcount; /* Step 1: allocate and initialize JPEG compression object */ - cinfo.err = jpeg_std_error(&jerr); + cinfo.err = jpeg_std_error(&jerr.pub); cinfo.err->error_exit = R_JPGErrorExit; cinfo.err->output_message = R_JPGOutputMessage; + /* Establish the setjmp return context for R_JPGErrorExit to use. */ + if (setjmp(jerr.setjmp_buffer)) + { + /* If we get here, the JPEG code has signaled an error. + * We need to clean up the JPEG object and return. + */ + jpeg_destroy_compress(&cinfo); + + ri.Printf(PRINT_ALL, "\n"); + return 0; + } + /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); -- cgit From e78dc015d1c94fbe4fa5014d412a2cdf23f2dc7d Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 21 Dec 2015 20:24:19 -0800 Subject: OpenGL2: Support picmip for DDS textures. --- src/renderergl2/tr_image.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index c35af4c2..74eddfe0 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -1869,7 +1869,7 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei int dataFormat, dataType; qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); - if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) + if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) { int bytesPer4x4Block = 0; int miplevel = 0; @@ -1877,6 +1877,7 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei switch (picFormat) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_RED_RGTC1: @@ -1901,11 +1902,26 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei break; } - for (miplevel = 0; miplevel < numMips; miplevel++) + if (flags & IMGFLAG_PICMIP) { - int size; + for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--) + { + int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; - size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; + x >>= 1; + y >>= 1; + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + data += size; + } + } + + if (!(flags & IMGFLAG_MIPMAP)) + numMips = 1; + + for (miplevel = 0; miplevel < numMips; miplevel++) + { + int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; if (subtexture) qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data); @@ -1914,9 +1930,6 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei x >>= 1; y >>= 1; - x -= x % 4; - y -= y % 4; - width = MAX(1, width >> 1); height = MAX(1, height >> 1); data += size; @@ -1956,29 +1969,20 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei if (flags & IMGFLAG_MIPMAP) { - int miplevel; + int miplevel = 0; - miplevel = 0; while (width > 1 || height > 1) { if (data) { if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - { R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); - } else - { R_MipMapsRGB( data, width, height ); - } } - width >>= 1; - height >>= 1; - if (width < 1) - width = 1; - if (height < 1) - height = 1; + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); miplevel++; if ( data && r_colorMipLevels->integer ) @@ -2029,7 +2033,7 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic } else if (!subtexture) { - if (picFormat != GL_RGBA8) + if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) { RawImage_UploadTexture(data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); goto done; -- cgit From 19c44d9c50d6a3057e79007c779552d0eb7fe4ef Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 22 Dec 2015 05:04:07 -0800 Subject: OpenGL2: Add r_exportCubemaps for saving cubemaps on map load. --- src/renderergl2/tr_bsp.c | 37 +++++++++++++++++++++++++++++++++- src/renderergl2/tr_image_dds.c | 45 ++++++++++++++++++++++++++++++++++++++++++ src/renderergl2/tr_init.c | 3 +++ src/renderergl2/tr_local.h | 1 + 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index d2a5f5f2..81463c66 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -3068,16 +3068,23 @@ void R_AssignCubemapsToWorldSurfaces(void) } } +// FIXME: put this function declaration elsewhere +void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth); void R_RenderAllCubemaps(void) { + byte *data = NULL; + int sideSize = CUBE_MAP_SIZE * CUBE_MAP_SIZE * 4; int i, j; for (i = 0; i < tr.numCubemaps; i++) { tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); } - + + if (r_exportCubemaps->integer) + data = ri.Malloc(sideSize * 6); + for (i = 0; i < tr.numCubemaps; i++) { for (j = 0; j < 6; j++) @@ -3087,6 +3094,34 @@ void R_RenderAllCubemaps(void) R_IssuePendingRenderCommands(); R_InitNextFrame(); } + + if (r_exportCubemaps->integer) + { + char filename[MAX_QPATH]; + byte *p; + cubemap_t *cubemap = &tr.cubemaps[i]; + + // FIXME: do this in backEnd + FBO_Bind(tr.renderCubeFbo); + + p = data; + for (j = 0; j < 6; j++) + { + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0); + qglReadPixels(0, 0, CUBE_MAP_SIZE, CUBE_MAP_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, p); + p += sideSize; + } + FBO_Bind(NULL); + + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, backEnd.viewParms.targetFboCubemapIndex); + R_SaveDDS(filename, data, CUBE_MAP_SIZE, CUBE_MAP_SIZE, 6); + } + } + + if (r_exportCubemaps->integer) + { + ri.Cvar_Set("r_exportCubemaps", "0"); + ri.Free(data); } } diff --git a/src/renderergl2/tr_image_dds.c b/src/renderergl2/tr_image_dds.c index 8ad406fd..b509014d 100644 --- a/src/renderergl2/tr_image_dds.c +++ b/src/renderergl2/tr_image_dds.c @@ -451,3 +451,48 @@ void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLen ri.FS_FreeFile(buffer.v); } + +void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth) +{ + byte *data; + ddsHeader_t *ddsHeader; + int picSize, size; + + if (!depth) + depth = 1; + + picSize = width * height * depth * 4; + size = 4 + sizeof(*ddsHeader) + picSize; + data = ri.Malloc(size); + + data[0] = 'D'; + data[1] = 'D'; + data[2] = 'S'; + data[3] = ' '; + + ddsHeader = (ddsHeader_t *)(data + 4); + memset(ddsHeader, 0, sizeof(ddsHeader_t)); + + ddsHeader->headerSize = 0x7c; + ddsHeader->flags = _DDSFLAGS_REQUIRED; + ddsHeader->height = height; + ddsHeader->width = width; + ddsHeader->always_0x00000020 = 0x00000020; + ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED; + + if (depth == 6) + ddsHeader->caps2 = DDSCAPS2_CUBEMAP; + + ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS; + ddsHeader->rgbBitCount = 32; + ddsHeader->rBitMask = 0x000000ff; + ddsHeader->gBitMask = 0x0000ff00; + ddsHeader->bBitMask = 0x00ff0000; + ddsHeader->aBitMask = 0xff000000; + + Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize); + + ri.FS_WriteFile(filename, data, size); + + ri.Free(data); +} diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 2828270e..44808639 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -141,6 +141,7 @@ cvar_t *r_specularMapping; cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; +cvar_t *r_exportCubemaps; cvar_t *r_specularIsMetallic; cvar_t *r_glossIsRoughness; cvar_t *r_baseNormalX; @@ -383,6 +384,7 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1); bufstart = PADP((intptr_t) buffer + *offset, packAlign); + qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart); *offset = bufstart - buffer; @@ -1141,6 +1143,7 @@ void R_Register( void ) r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_exportCubemaps = ri.Cvar_Get("r_exportCubemaps", "0", 0); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 0a1dc5fe..f716065e 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1794,6 +1794,7 @@ extern cvar_t *r_specularMapping; extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; +extern cvar_t *r_exportCubemaps; extern cvar_t *r_specularIsMetallic; extern cvar_t *r_glossIsRoughness; extern cvar_t *r_baseNormalX; -- cgit From cedfa02c6b3b17cda26202abf5e4dd32f9720cb5 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 23 Dec 2015 09:58:11 -0800 Subject: OpenGL2: Replace r_exportCubemaps cvar with exportCubemaps command. --- src/renderergl2/tr_backend.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ src/renderergl2/tr_bsp.c | 35 ------------------------- src/renderergl2/tr_init.c | 33 +++++++++++++++++++++-- src/renderergl2/tr_local.h | 8 ++++-- 4 files changed, 99 insertions(+), 39 deletions(-) diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index ad43e5b2..4a29c966 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -1738,6 +1738,65 @@ const void *RB_PostProcess(const void *data) return (const void *)(cmd + 1); } +// FIXME: put this function declaration elsewhere +void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth); + +/* +============= +RB_ExportCubemaps + +============= +*/ +const void *RB_ExportCubemaps(const void *data) +{ + const exportCubemapsCommand_t *cmd = data; + + // finish any 2D drawing if needed + if (tess.numIndexes) + RB_EndSurface(); + + if (!glRefConfig.framebufferObject || !tr.world || tr.numCubemaps == 0) + { + // do nothing + ri.Printf(PRINT_ALL, "Nothing to export!\n"); + return (const void *)(cmd + 1); + } + + if (cmd) + { + FBO_t *oldFbo = glState.currentFBO; + int sideSize = CUBE_MAP_SIZE * CUBE_MAP_SIZE * 4; + byte *cubemapPixels = ri.Malloc(sideSize * 6); + int i, j; + + FBO_Bind(tr.renderCubeFbo); + + for (i = 0; i < tr.numCubemaps; i++) + { + char filename[MAX_QPATH]; + cubemap_t *cubemap = &tr.cubemaps[i]; + char *p = cubemapPixels; + + for (j = 0; j < 6; j++) + { + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0); + qglReadPixels(0, 0, CUBE_MAP_SIZE, CUBE_MAP_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, p); + p += sideSize; + } + + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); + R_SaveDDS(filename, cubemapPixels, CUBE_MAP_SIZE, CUBE_MAP_SIZE, 6); + ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename); + } + + FBO_Bind(oldFbo); + + ri.Free(cubemapPixels); + } + + return (const void *)(cmd + 1); +} + /* ==================== @@ -1786,6 +1845,9 @@ void RB_ExecuteRenderCommands( const void *data ) { case RC_POSTPROCESS: data = RB_PostProcess(data); break; + case RC_EXPORT_CUBEMAPS: + data = RB_ExportCubemaps(data); + break; case RC_END_OF_LIST: default: // finish any 2D drawing if needed diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index 81463c66..960e9282 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -3068,13 +3068,9 @@ void R_AssignCubemapsToWorldSurfaces(void) } } -// FIXME: put this function declaration elsewhere -void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth); void R_RenderAllCubemaps(void) { - byte *data = NULL; - int sideSize = CUBE_MAP_SIZE * CUBE_MAP_SIZE * 4; int i, j; for (i = 0; i < tr.numCubemaps; i++) @@ -3082,9 +3078,6 @@ void R_RenderAllCubemaps(void) tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); } - if (r_exportCubemaps->integer) - data = ri.Malloc(sideSize * 6); - for (i = 0; i < tr.numCubemaps; i++) { for (j = 0; j < 6; j++) @@ -3094,34 +3087,6 @@ void R_RenderAllCubemaps(void) R_IssuePendingRenderCommands(); R_InitNextFrame(); } - - if (r_exportCubemaps->integer) - { - char filename[MAX_QPATH]; - byte *p; - cubemap_t *cubemap = &tr.cubemaps[i]; - - // FIXME: do this in backEnd - FBO_Bind(tr.renderCubeFbo); - - p = data; - for (j = 0; j < 6; j++) - { - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0); - qglReadPixels(0, 0, CUBE_MAP_SIZE, CUBE_MAP_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, p); - p += sideSize; - } - FBO_Bind(NULL); - - Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, backEnd.viewParms.targetFboCubemapIndex); - R_SaveDDS(filename, data, CUBE_MAP_SIZE, CUBE_MAP_SIZE, 6); - } - } - - if (r_exportCubemaps->integer) - { - ri.Cvar_Set("r_exportCubemaps", "0"); - ri.Free(data); } } diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 44808639..8a84c1f8 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -141,7 +141,6 @@ cvar_t *r_specularMapping; cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; -cvar_t *r_exportCubemaps; cvar_t *r_specularIsMetallic; cvar_t *r_glossIsRoughness; cvar_t *r_baseNormalX; @@ -760,6 +759,35 @@ void R_ScreenShotJPEG_f (void) { //============================================================================ +/* +================== +R_ExportCubemaps +================== +*/ +void R_ExportCubemaps() +{ + exportCubemapsCommand_t *cmd; + + cmd = R_GetCommandBuffer(sizeof(*cmd)); + if (!cmd) { + return; + } + cmd->commandId = RC_EXPORT_CUBEMAPS; +} + + +/* +================== +R_ExportCubemaps_f +================== +*/ +void R_ExportCubemaps_f(void) +{ + R_ExportCubemaps(); +} + +//============================================================================ + /* ================== RB_TakeVideoFrameCmd @@ -1143,7 +1171,6 @@ void R_Register( void ) r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_exportCubemaps = ri.Cvar_Get("r_exportCubemaps", "0", 0); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); @@ -1280,6 +1307,7 @@ void R_Register( void ) ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f ); ri.Cmd_AddCommand( "minimize", GLimp_Minimize ); ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f ); + ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f ); } void R_InitQueries(void) @@ -1421,6 +1449,7 @@ void RE_Shutdown( qboolean destroyWindow ) { ri.Cmd_RemoveCommand("minimize"); ri.Cmd_RemoveCommand( "shaderstate" ); ri.Cmd_RemoveCommand( "gfxmeminfo" ); + ri.Cmd_RemoveCommand( "exportCubemaps" ); if ( tr.registered ) { diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index f716065e..a652a396 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1794,7 +1794,6 @@ extern cvar_t *r_specularMapping; extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; -extern cvar_t *r_exportCubemaps; extern cvar_t *r_specularIsMetallic; extern cvar_t *r_glossIsRoughness; extern cvar_t *r_baseNormalX; @@ -2422,6 +2421,10 @@ typedef struct { viewParms_t viewParms; } postProcessCommand_t; +typedef struct { + int commandId; +} exportCubemapsCommand_t; + typedef enum { RC_END_OF_LIST, RC_SET_COLOR, @@ -2434,7 +2437,8 @@ typedef enum { RC_COLORMASK, RC_CLEARDEPTH, RC_CAPSHADOWMAP, - RC_POSTPROCESS + RC_POSTPROCESS, + RC_EXPORT_CUBEMAPS } renderCommand_t; -- cgit From fae2cb94e089fabe9a69d0909a5c25e1014cb25f Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 24 Dec 2015 16:34:58 -0800 Subject: OpenGL2: Add r_cubemapSize. --- src/renderergl2/tr_backend.c | 6 +++--- src/renderergl2/tr_bsp.c | 2 +- src/renderergl2/tr_image.c | 2 +- src/renderergl2/tr_init.c | 2 ++ src/renderergl2/tr_local.h | 3 +-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 4a29c966..557f553b 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -1765,7 +1765,7 @@ const void *RB_ExportCubemaps(const void *data) if (cmd) { FBO_t *oldFbo = glState.currentFBO; - int sideSize = CUBE_MAP_SIZE * CUBE_MAP_SIZE * 4; + int sideSize = r_cubemapSize->integer * r_cubemapSize->integer * 4; byte *cubemapPixels = ri.Malloc(sideSize * 6); int i, j; @@ -1780,12 +1780,12 @@ const void *RB_ExportCubemaps(const void *data) for (j = 0; j < 6; j++) { qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0); - qglReadPixels(0, 0, CUBE_MAP_SIZE, CUBE_MAP_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, p); + qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p); p += sideSize; } Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); - R_SaveDDS(filename, cubemapPixels, CUBE_MAP_SIZE, CUBE_MAP_SIZE, 6); + R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6); ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename); } diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index 960e9282..e0a97d4d 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -3075,7 +3075,7 @@ void R_RenderAllCubemaps(void) for (i = 0; i < tr.numCubemaps; i++) { - tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); + tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); } for (i = 0; i < tr.numCubemaps; i++) diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 74eddfe0..d01f42c4 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -2842,7 +2842,7 @@ void R_CreateBuiltinImages( void ) { if (r_cubeMapping->integer) { - tr.renderCubeImage = R_CreateImage("*renderCube", NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat); + tr.renderCubeImage = R_CreateImage("*renderCube", NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat); } } } diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 8a84c1f8..bf05e210 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -141,6 +141,7 @@ cvar_t *r_specularMapping; cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; +cvar_t *r_cubemapSize; cvar_t *r_specularIsMetallic; cvar_t *r_glossIsRoughness; cvar_t *r_baseNormalX; @@ -1171,6 +1172,7 @@ void R_Register( void ) r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); + r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH ); r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index a652a396..72f11989 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -55,8 +55,6 @@ typedef unsigned int glIndex_t; #define MAX_CALC_PSHADOWS 64 #define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces #define PSHADOW_MAP_SIZE 512 -#define CUBE_MAP_MIPS 7 -#define CUBE_MAP_SIZE (1 << CUBE_MAP_MIPS) #define USE_VERT_TANGENT_SPACE #define USE_OVERBRIGHT @@ -1794,6 +1792,7 @@ extern cvar_t *r_specularMapping; extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; +extern cvar_t *r_cubemapSize; extern cvar_t *r_specularIsMetallic; extern cvar_t *r_glossIsRoughness; extern cvar_t *r_baseNormalX; -- cgit From 975d4d97e4b9459c3d21b4dc3ecd807e9c330d9a Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 10 Dec 2013 21:14:13 -0600 Subject: Use Opus for VoIP Server/client VoIP protocol is handled by adding new cvars cl_voipProtocol and sv_voipProtocol, sv_voip and cl_voip are used to auto set/clear them. All users need to touch are cl/sv_voip as 0 or 1 just like before. Old Speex VoIP packets in demos are skipped. New VoIP packets are skipped in demos if sv_voipProtocol doesn't match cl_voipProtocol. Notable difference between usage of speex and opus codecs, when using Speex client would be sent 80ms at a time. Using Opus, 60ms is sent at a time. This was changed because the Opus codec supports encoding up to 60ms at a time. (Simpler to send only one codec frame in a packet.) --- Makefile | 76 +++++---------------------------- src/client/cl_cgame.c | 36 ++++++---------- src/client/cl_input.c | 4 +- src/client/cl_main.c | 108 +++++++++++++++++++++-------------------------- src/client/cl_parse.c | 105 ++++++++++++++++++++++----------------------- src/client/client.h | 21 ++++----- src/client/snd_openal.c | 8 +--- src/qcommon/qcommon.h | 6 ++- src/server/server.h | 3 +- src/server/sv_client.c | 22 +++++++--- src/server/sv_init.c | 3 +- src/server/sv_main.c | 5 ++- src/server/sv_snapshot.c | 2 +- 13 files changed, 165 insertions(+), 234 deletions(-) diff --git a/Makefile b/Makefile index c1a5b29e..99c184b5 100644 --- a/Makefile +++ b/Makefile @@ -188,10 +188,6 @@ ifndef USE_INTERNAL_LIBS USE_INTERNAL_LIBS=1 endif -ifndef USE_INTERNAL_SPEEX -USE_INTERNAL_SPEEX=$(USE_INTERNAL_LIBS) -endif - ifndef USE_INTERNAL_OGG USE_INTERNAL_OGG=$(USE_INTERNAL_LIBS) endif @@ -246,7 +242,6 @@ CGDIR=$(MOUNT_DIR)/cgame NDIR=$(MOUNT_DIR)/null UIDIR=$(MOUNT_DIR)/ui JPDIR=$(MOUNT_DIR)/jpeg-8c -SPEEXDIR=$(MOUNT_DIR)/libspeex OGGDIR=$(MOUNT_DIR)/libogg-1.3.1 VORBISDIR=$(MOUNT_DIR)/libvorbis-1.3.4 OPUSDIR=$(MOUNT_DIR)/opus-1.1 @@ -962,8 +957,18 @@ ifeq ($(USE_CURL),1) endif endif +ifeq ($(USE_VOIP),1) + CLIENT_CFLAGS += -DUSE_VOIP + SERVER_CFLAGS += -DUSE_VOIP + NEED_OPUS=1 +endif + ifeq ($(USE_CODEC_OPUS),1) CLIENT_CFLAGS += -DUSE_CODEC_OPUS + NEED_OPUS=1 +endif + +ifeq ($(NEED_OPUS),1) ifeq ($(USE_INTERNAL_OPUS),1) OPUS_CFLAGS = -DOPUS_BUILD -DHAVE_LRINTF -DFLOATING_POINT -DUSE_ALLOCA \ -I$(OPUSDIR)/include -I$(OPUSDIR)/celt -I$(OPUSDIR)/silk \ @@ -1009,19 +1014,6 @@ ifeq ($(USE_MUMBLE),1) CLIENT_CFLAGS += -DUSE_MUMBLE endif -ifeq ($(USE_VOIP),1) - CLIENT_CFLAGS += -DUSE_VOIP - SERVER_CFLAGS += -DUSE_VOIP - ifeq ($(USE_INTERNAL_SPEEX),1) - SPEEX_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include - else - SPEEX_CFLAGS ?= $(shell pkg-config --silence-errors --cflags speex speexdsp || true) - SPEEX_LIBS ?= $(shell pkg-config --silence-errors --libs speex speexdsp || echo -lspeex -lspeexdsp) - endif - CLIENT_CFLAGS += $(SPEEX_CFLAGS) - CLIENT_LIBS += $(SPEEX_LIBS) -endif - ifeq ($(USE_INTERNAL_ZLIB),1) ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR) else @@ -1722,53 +1714,7 @@ ifeq ($(ARCH),x86_64) $(B)/client/ftola.o endif -ifeq ($(USE_VOIP),1) -ifeq ($(USE_INTERNAL_SPEEX),1) -Q3OBJ += \ - $(B)/client/bits.o \ - $(B)/client/buffer.o \ - $(B)/client/cb_search.o \ - $(B)/client/exc_10_16_table.o \ - $(B)/client/exc_10_32_table.o \ - $(B)/client/exc_20_32_table.o \ - $(B)/client/exc_5_256_table.o \ - $(B)/client/exc_5_64_table.o \ - $(B)/client/exc_8_128_table.o \ - $(B)/client/fftwrap.o \ - $(B)/client/filterbank.o \ - $(B)/client/filters.o \ - $(B)/client/gain_table.o \ - $(B)/client/gain_table_lbr.o \ - $(B)/client/hexc_10_32_table.o \ - $(B)/client/hexc_table.o \ - $(B)/client/high_lsp_tables.o \ - $(B)/client/jitter.o \ - $(B)/client/kiss_fft.o \ - $(B)/client/kiss_fftr.o \ - $(B)/client/lpc.o \ - $(B)/client/lsp.o \ - $(B)/client/lsp_tables_nb.o \ - $(B)/client/ltp.o \ - $(B)/client/mdf.o \ - $(B)/client/modes.o \ - $(B)/client/modes_wb.o \ - $(B)/client/nb_celp.o \ - $(B)/client/preprocess.o \ - $(B)/client/quant_lsp.o \ - $(B)/client/resample.o \ - $(B)/client/sb_celp.o \ - $(B)/client/smallft.o \ - $(B)/client/speex.o \ - $(B)/client/speex_callbacks.o \ - $(B)/client/speex_header.o \ - $(B)/client/stereo.o \ - $(B)/client/vbr.o \ - $(B)/client/vq.o \ - $(B)/client/window.o -endif -endif - -ifeq ($(USE_CODEC_OPUS),1) +ifeq ($(NEED_OPUS),1) ifeq ($(USE_INTERNAL_OPUS),1) Q3OBJ += \ $(B)/client/opus/analysis.o \ diff --git a/src/client/cl_cgame.c b/src/client/cl_cgame.c index 1c7d91cc..23f3010c 100644 --- a/src/client/cl_cgame.c +++ b/src/client/cl_cgame.c @@ -956,37 +956,27 @@ void CL_FirstSnapshot( void ) { #endif #ifdef USE_VOIP - if (!clc.speexInitialized) { + if (!clc.voipCodecInitialized) { int i; - speex_bits_init(&clc.speexEncoderBits); - speex_bits_reset(&clc.speexEncoderBits); + int error; - clc.speexEncoder = speex_encoder_init(&speex_nb_mode); + clc.opusEncoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error); - speex_encoder_ctl(clc.speexEncoder, SPEEX_GET_FRAME_SIZE, - &clc.speexFrameSize); - speex_encoder_ctl(clc.speexEncoder, SPEEX_GET_SAMPLING_RATE, - &clc.speexSampleRate); - - clc.speexPreprocessor = speex_preprocess_state_init(clc.speexFrameSize, - clc.speexSampleRate); - - i = 1; - speex_preprocess_ctl(clc.speexPreprocessor, - SPEEX_PREPROCESS_SET_DENOISE, &i); - - i = 1; - speex_preprocess_ctl(clc.speexPreprocessor, - SPEEX_PREPROCESS_SET_AGC, &i); + if ( error ) { + Com_DPrintf("VoIP: Error opus_encoder_create %d\n", error); + return; + } for (i = 0; i < MAX_CLIENTS; i++) { - speex_bits_init(&clc.speexDecoderBits[i]); - speex_bits_reset(&clc.speexDecoderBits[i]); - clc.speexDecoder[i] = speex_decoder_init(&speex_nb_mode); + clc.opusDecoder[i] = opus_decoder_create(48000, 1, &error); + if ( error ) { + Com_DPrintf("VoIP: Error opus_decoder_create(%d) %d\n", i, error); + return; + } clc.voipIgnore[i] = qfalse; clc.voipGain[i] = 1.0f; } - clc.speexInitialized = qtrue; + clc.voipCodecInitialized = qtrue; clc.voipMuteAll = qfalse; Cmd_AddCommand ("voip", CL_Voip_f); Cvar_Set("cl_voipSendTarget", "spatial"); diff --git a/src/client/cl_input.c b/src/client/cl_input.c index fdd0c474..48bf51df 100644 --- a/src/client/cl_input.c +++ b/src/client/cl_input.c @@ -789,7 +789,7 @@ void CL_WritePacket( void ) { { if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1)) { - MSG_WriteByte (&buf, clc_voip); + MSG_WriteByte (&buf, clc_voipOpus); MSG_WriteByte (&buf, clc.voipOutgoingGeneration); MSG_WriteLong (&buf, clc.voipOutgoingSequence); MSG_WriteByte (&buf, clc.voipOutgoingDataFrames); @@ -810,7 +810,7 @@ void CL_WritePacket( void ) { MSG_Init (&fakemsg, fakedata, sizeof (fakedata)); MSG_Bitstream (&fakemsg); MSG_WriteLong (&fakemsg, clc.reliableAcknowledge); - MSG_WriteByte (&fakemsg, svc_voip); + MSG_WriteByte (&fakemsg, svc_voipOpus); MSG_WriteShort (&fakemsg, clc.clientNum); MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration); MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence); diff --git a/src/client/cl_main.c b/src/client/cl_main.c index fa47988e..6df57b4d 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -45,6 +45,7 @@ cvar_t *cl_voipSendTarget; cvar_t *cl_voipGainDuringCapture; cvar_t *cl_voipCaptureMult; cvar_t *cl_voipShowMeter; +cvar_t *cl_voipProtocol; cvar_t *cl_voip; #endif @@ -250,8 +251,8 @@ void CL_Voip_f( void ) if (clc.state != CA_ACTIVE) reason = "Not connected to a server"; - else if (!clc.speexInitialized) - reason = "Speex not initialized"; + else if (!clc.voipCodecInitialized) + reason = "Voip codec not initialized"; else if (!clc.voipEnabled) reason = "Server doesn't support VoIP"; @@ -304,6 +305,8 @@ void CL_VoipNewGeneration(void) clc.voipOutgoingGeneration = 1; clc.voipPower = 0.0f; clc.voipOutgoingSequence = 0; + + opus_encoder_ctl(clc.opusEncoder, OPUS_RESET_STATE); } /* @@ -392,7 +395,7 @@ void CL_VoipParseTargets(void) =============== CL_CaptureVoip -Record more audio from the hardware if required and encode it into Speex +Record more audio from the hardware if required and encode it into Opus data for later transmission. =============== */ @@ -422,11 +425,12 @@ void CL_CaptureVoip(void) Com_Printf("Until then, VoIP is disabled.\n"); Cvar_Set("cl_voip", "0"); } + Cvar_Set("cl_voipProtocol", cl_voip->integer ? "opus" : ""); cl_voip->modified = qfalse; cl_rate->modified = qfalse; } - if (!clc.speexInitialized) + if (!clc.voipCodecInitialized) return; // just in case this gets called at a bad time. if (clc.voipOutgoingDataSize > 0) @@ -479,80 +483,67 @@ void CL_CaptureVoip(void) if ((cl_voipSend->integer) || (finalFrame)) { // user wants to capture audio? int samples = S_AvailableCaptureSamples(); - const int mult = (finalFrame) ? 1 : 4; // 4 == 80ms of audio. + const int packetSamples = (finalFrame) ? VOIP_MAX_FRAME_SAMPLES : VOIP_MAX_PACKET_SAMPLES; // enough data buffered in audio hardware to process yet? - if (samples >= (clc.speexFrameSize * mult)) { - // audio capture is always MONO16 (and that's what speex wants!). - // 2048 will cover 12 uncompressed frames in narrowband mode. - static int16_t sampbuffer[2048]; + if (samples >= packetSamples) { + // audio capture is always MONO16. + static int16_t sampbuffer[VOIP_MAX_PACKET_SAMPLES]; float voipPower = 0.0f; - int speexFrames = 0; - int wpos = 0; - int pos = 0; + int voipFrames; + int i, bytes; - if (samples > (clc.speexFrameSize * 4)) - samples = (clc.speexFrameSize * 4); + if (samples > VOIP_MAX_PACKET_SAMPLES) + samples = VOIP_MAX_PACKET_SAMPLES; // !!! FIXME: maybe separate recording from encoding, so voipPower // !!! FIXME: updates faster than 4Hz? - samples -= samples % clc.speexFrameSize; - S_Capture(samples, (byte *) sampbuffer); // grab from audio card. - - // this will probably generate multiple speex packets each time. - while (samples > 0) { - int16_t *sampptr = &sampbuffer[pos]; - int i, bytes; + samples -= samples % VOIP_MAX_FRAME_SAMPLES; + if (samples != 120 && samples != 240 && samples != 480 && samples != 960 && samples != 1920 && samples != 2880 ) { + Com_Printf("Voip: bad number of samples %d\n", samples); + return; + } + voipFrames = samples / VOIP_MAX_FRAME_SAMPLES; - // preprocess samples to remove noise... - speex_preprocess_run(clc.speexPreprocessor, sampptr); + S_Capture(samples, (byte *) sampbuffer); // grab from audio card. - // check the "power" of this packet... - for (i = 0; i < clc.speexFrameSize; i++) { - const float flsamp = (float) sampptr[i]; - const float s = fabs(flsamp); - voipPower += s * s; - sampptr[i] = (int16_t) ((flsamp) * audioMult); - } + // check the "power" of this packet... + for (i = 0; i < samples; i++) { + const float flsamp = (float) sampbuffer[i]; + const float s = fabs(flsamp); + voipPower += s * s; + sampbuffer[i] = (int16_t) ((flsamp) * audioMult); + } - // encode raw audio samples into Speex data... - speex_bits_reset(&clc.speexEncoderBits); - speex_encode_int(clc.speexEncoder, sampptr, - &clc.speexEncoderBits); - bytes = speex_bits_write(&clc.speexEncoderBits, - (char *) &clc.voipOutgoingData[wpos+1], - sizeof (clc.voipOutgoingData) - (wpos+1)); - assert((bytes > 0) && (bytes < 256)); - clc.voipOutgoingData[wpos] = (byte) bytes; - wpos += bytes + 1; - - // look at the data for the next packet... - pos += clc.speexFrameSize; - samples -= clc.speexFrameSize; - speexFrames++; + // encode raw audio samples into Opus data... + bytes = opus_encode(clc.opusEncoder, sampbuffer, samples, + (unsigned char *) clc.voipOutgoingData, + sizeof (clc.voipOutgoingData)); + if ( bytes <= 0 ) { + Com_DPrintf("VoIP: Error encoding %d samples\n", samples); + bytes = 0; } clc.voipPower = (voipPower / (32768.0f * 32768.0f * - ((float) (clc.speexFrameSize * speexFrames)))) * - 100.0f; + ((float) samples))) * 100.0f; if ((useVad) && (clc.voipPower < cl_voipVADThreshold->value)) { CL_VoipNewGeneration(); // no "talk" for at least 1/4 second. } else { - clc.voipOutgoingDataSize = wpos; - clc.voipOutgoingDataFrames = speexFrames; + clc.voipOutgoingDataSize = bytes; + clc.voipOutgoingDataFrames = voipFrames; Com_DPrintf("VoIP: Send %d frames, %d bytes, %f power\n", - speexFrames, wpos, clc.voipPower); + voipFrames, bytes, clc.voipPower); #if 0 static FILE *encio = NULL; if (encio == NULL) encio = fopen("voip-outgoing-encoded.bin", "wb"); - if (encio != NULL) { fwrite(clc.voipOutgoingData, wpos, 1, encio); fflush(encio); } + if (encio != NULL) { fwrite(clc.voipOutgoingData, bytes, 1, encio); fflush(encio); } static FILE *decio = NULL; if (decio == NULL) decio = fopen("voip-outgoing-decoded.bin", "wb"); - if (decio != NULL) { fwrite(sampbuffer, speexFrames * clc.speexFrameSize * 2, 1, decio); fflush(decio); } + if (decio != NULL) { fwrite(sampbuffer, voipFrames * VOIP_MAX_FRAME_SAMPLES * 2, 1, decio); fflush(decio); } #endif } } @@ -1419,14 +1410,11 @@ void CL_Disconnect( qboolean showMainMenu ) { cl_voipUseVAD->integer = tmp; } - if (clc.speexInitialized) { + if (clc.voipCodecInitialized) { int i; - speex_bits_destroy(&clc.speexEncoderBits); - speex_encoder_destroy(clc.speexEncoder); - speex_preprocess_state_destroy(clc.speexPreprocessor); + opus_encoder_destroy(clc.opusEncoder); for (i = 0; i < MAX_CLIENTS; i++) { - speex_bits_destroy(&clc.speexDecoderBits[i]); - speex_decoder_destroy(clc.speexDecoder[i]); + opus_decoder_destroy(clc.opusDecoder[i]); } } Cmd_RemoveCommand ("voip"); @@ -3706,9 +3694,9 @@ void CL_Init( void ) { cl_voipVADThreshold = Cvar_Get ("cl_voipVADThreshold", "0.25", CVAR_ARCHIVE); cl_voipShowMeter = Cvar_Get ("cl_voipShowMeter", "1", CVAR_ARCHIVE); - // This is a protocol version number. - cl_voip = Cvar_Get ("cl_voip", "1", CVAR_USERINFO | CVAR_ARCHIVE); + cl_voip = Cvar_Get ("cl_voip", "1", CVAR_ARCHIVE); Cvar_CheckRange( cl_voip, 0, 1, qtrue ); + cl_voipProtocol = Cvar_Get ("cl_voipProtocol", cl_voip->integer ? "opus" : "", CVAR_USERINFO | CVAR_ROM); #endif diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c index a8b68ca5..4230c04f 100644 --- a/src/client/cl_parse.c +++ b/src/client/cl_parse.c @@ -35,7 +35,8 @@ char *svc_strings[256] = { "svc_download", "svc_snapshot", "svc_EOF", - "svc_voip", + "svc_voipSpeex", + "svc_voipOpus", }; void SHOWNET( msg_t *msg, char *s) { @@ -354,8 +355,8 @@ void CL_SystemInfoChanged( void ) { cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) ); #ifdef USE_VOIP - s = Info_ValueForKey( systemInfo, "sv_voip" ); - clc.voipEnabled = atoi(s); + s = Info_ValueForKey( systemInfo, "sv_voipProtocol" ); + clc.voipEnabled = !Q_stricmp(s, "opus"); #endif // don't set any vars when playing a demo @@ -674,13 +675,13 @@ static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags) { if(flags & VOIP_DIRECT) { - S_RawSamples(sender + 1, samplecnt, clc.speexSampleRate, 2, 1, + S_RawSamples(sender + 1, samplecnt, 48000, 2, 1, data, clc.voipGain[sender], -1); } if(flags & VOIP_SPATIAL) { - S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, clc.speexSampleRate, 2, 1, + S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, 48000, 2, 1, data, 1.0f, sender); } } @@ -693,8 +694,8 @@ A VoIP message has been received from the server ===================== */ static -void CL_ParseVoip ( msg_t *msg ) { - static short decoded[4096]; // !!! FIXME: don't hardcode. +void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) { + static short decoded[VOIP_MAX_PACKET_SAMPLES*4]; // !!! FIXME: don't hard code const int sender = MSG_ReadShort(msg); const int generation = MSG_ReadByte(msg); @@ -702,7 +703,8 @@ void CL_ParseVoip ( msg_t *msg ) { const int frames = MSG_ReadByte(msg); const int packetsize = MSG_ReadShort(msg); const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT); - char encoded[1024]; + unsigned char encoded[4000]; + int numSamples; int seqdiff; int written = 0; int i; @@ -732,14 +734,15 @@ void CL_ParseVoip ( msg_t *msg ) { return; // overlarge packet, bail. } - if (!clc.speexInitialized) { - MSG_ReadData(msg, encoded, packetsize); // skip payload. - return; // can't handle VoIP without libspeex! + MSG_ReadData(msg, encoded, packetsize); + + if (ignoreData) { + return; // just ignore legacy speex voip data + } else if (!clc.voipCodecInitialized) { + return; // can't handle VoIP without libopus! } else if (sender >= MAX_CLIENTS) { - MSG_ReadData(msg, encoded, packetsize); // skip payload. return; // bogus sender. } else if (CL_ShouldIgnoreVoipSender(sender)) { - MSG_ReadData(msg, encoded, packetsize); // skip payload. return; // Channel is muted, bail. } @@ -752,70 +755,59 @@ void CL_ParseVoip ( msg_t *msg ) { // This is a new "generation" ... a new recording started, reset the bits. if (generation != clc.voipIncomingGeneration[sender]) { Com_DPrintf("VoIP: new generation %d!\n", generation); - speex_bits_reset(&clc.speexDecoderBits[sender]); + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); clc.voipIncomingGeneration[sender] = generation; seqdiff = 0; } else if (seqdiff < 0) { // we're ahead of the sequence?! // This shouldn't happen unless the packet is corrupted or something. Com_DPrintf("VoIP: misordered sequence! %d < %d!\n", sequence, clc.voipIncomingSequence[sender]); - // reset the bits just in case. - speex_bits_reset(&clc.speexDecoderBits[sender]); + // reset the decoder just in case. + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); seqdiff = 0; - } else if (seqdiff * clc.speexFrameSize * 2 >= sizeof (decoded)) { // dropped more than we can handle? + } else if (seqdiff * VOIP_MAX_PACKET_SAMPLES*2 >= sizeof (decoded)) { // dropped more than we can handle? // just start over. Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n", seqdiff, sender); - speex_bits_reset(&clc.speexDecoderBits[sender]); + opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE); seqdiff = 0; } if (seqdiff != 0) { Com_DPrintf("VoIP: Dropped %d frames from client #%d\n", seqdiff, sender); - // tell speex that we're missing frames... + // tell opus that we're missing frames... for (i = 0; i < seqdiff; i++) { - assert((written + clc.speexFrameSize) * 2 < sizeof (decoded)); - speex_decode_int(clc.speexDecoder[sender], NULL, decoded + written); - written += clc.speexFrameSize; + assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded)); + numSamples = opus_decode(clc.opusDecoder[sender], NULL, VOIP_MAX_PACKET_SAMPLES * 2, decoded + written, sizeof (decoded) - written, 0); + if ( numSamples <= 0 ) { + Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender); + continue; + } + written += numSamples; } } - for (i = 0; i < frames; i++) { - const int len = MSG_ReadByte(msg); - if (len < 0) { - Com_DPrintf("VoIP: Short packet!\n"); - break; - } - MSG_ReadData(msg, encoded, len); + numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, sizeof (decoded) - written, 0); - // shouldn't happen, but just in case... - if ((written + clc.speexFrameSize) * 2 > sizeof (decoded)) { - Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n", - written * 2, written, i); - - CL_PlayVoip(sender, written, (const byte *) decoded, flags); - written = 0; - } - - speex_bits_read_from(&clc.speexDecoderBits[sender], encoded, len); - speex_decode_int(clc.speexDecoder[sender], - &clc.speexDecoderBits[sender], decoded + written); + if ( numSamples <= 0 ) { + Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender); + numSamples = 0; + } - #if 0 - static FILE *encio = NULL; - if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb"); - if (encio != NULL) { fwrite(encoded, len, 1, encio); fflush(encio); } - static FILE *decio = NULL; - if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb"); - if (decio != NULL) { fwrite(decoded+written, clc.speexFrameSize*2, 1, decio); fflush(decio); } - #endif + #if 0 + static FILE *encio = NULL; + if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb"); + if (encio != NULL) { fwrite(encoded, len, 1, encio); fflush(encio); } + static FILE *decio = NULL; + if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb"); + if (decio != NULL) { fwrite(decoded+written, clc.speexFrameSize*2, 1, decio); fflush(decio); } + #endif - written += clc.speexFrameSize; - } + written += numSamples; Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n", - written * 2, written, i); + written * 2, written, frames); if(written > 0) CL_PlayVoip(sender, written, (const byte *) decoded, flags); @@ -918,9 +910,14 @@ void CL_ParseServerMessage( msg_t *msg ) { case svc_download: CL_ParseDownload( msg ); break; - case svc_voip: + case svc_voipSpeex: +#ifdef USE_VOIP + CL_ParseVoip( msg, qtrue ); +#endif + break; + case svc_voipOpus: #ifdef USE_VOIP - CL_ParseVoip( msg ); + CL_ParseVoip( msg, !clc.voipEnabled ); #endif break; } diff --git a/src/client/client.h b/src/client/client.h index 541dca40..b4016467 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -36,8 +36,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif /* USE_CURL */ #ifdef USE_VOIP -#include "speex/speex.h" -#include "speex/speex_preprocess.h" +#include #endif // file full of random crap that gets used to create cl_guid @@ -241,14 +240,11 @@ typedef struct { #ifdef USE_VOIP qboolean voipEnabled; - qboolean speexInitialized; - int speexFrameSize; - int speexSampleRate; + qboolean voipCodecInitialized; // incoming data... // !!! FIXME: convert from parallel arrays to array of a struct. - SpeexBits speexDecoderBits[MAX_CLIENTS]; - void *speexDecoder[MAX_CLIENTS]; + OpusDecoder *opusDecoder[MAX_CLIENTS]; byte voipIncomingGeneration[MAX_CLIENTS]; int voipIncomingSequence[MAX_CLIENTS]; float voipGain[MAX_CLIENTS]; @@ -260,9 +256,7 @@ typedef struct { // then we are sending to clientnum i. uint8_t voipTargets[(MAX_CLIENTS + 7) / 8]; uint8_t voipFlags; - SpeexPreprocessState *speexPreprocessor; - SpeexBits speexEncoderBits; - void *speexEncoder; + OpusEncoder *opusEncoder; int voipOutgoingDataSize; int voipOutgoingDataFrames; int voipOutgoingSequence; @@ -449,6 +443,13 @@ extern cvar_t *cl_voipGainDuringCapture; extern cvar_t *cl_voipCaptureMult; extern cvar_t *cl_voipShowMeter; extern cvar_t *cl_voip; + +// 20ms at 48k +#define VOIP_MAX_FRAME_SAMPLES ( 20 * 48 ) + +// 3 frame is 60ms of audio, the max opus will encode at once +#define VOIP_MAX_PACKET_FRAMES 3 +#define VOIP_MAX_PACKET_SAMPLES ( VOIP_MAX_FRAME_SAMPLES * VOIP_MAX_PACKET_FRAMES ) #endif //================================================= diff --git a/src/client/snd_openal.c b/src/client/snd_openal.c index d90e6d23..b5c89918 100644 --- a/src/client/snd_openal.c +++ b/src/client/snd_openal.c @@ -2700,16 +2700,12 @@ qboolean S_AL_Init( soundInterface_t *si ) s_alAvailableInputDevices = Cvar_Get("s_alAvailableInputDevices", inputdevicenames, CVAR_ROM | CVAR_NORESTART); - // !!! FIXME: 8000Hz is what Speex narrowband mode needs, but we - // !!! FIXME: should probably open the capture device after - // !!! FIXME: initializing Speex so we can change to wideband - // !!! FIXME: if we like. Com_Printf("OpenAL default capture device is '%s'\n", defaultinputdevice ? defaultinputdevice : "none"); - alCaptureDevice = qalcCaptureOpenDevice(inputdevice, 8000, AL_FORMAT_MONO16, 4096); + alCaptureDevice = qalcCaptureOpenDevice(inputdevice, 48000, AL_FORMAT_MONO16, VOIP_MAX_PACKET_SAMPLES*4); if( !alCaptureDevice && inputdevice ) { Com_Printf( "Failed to open OpenAL Input device '%s', trying default.\n", inputdevice ); - alCaptureDevice = qalcCaptureOpenDevice(NULL, 8000, AL_FORMAT_MONO16, 4096); + alCaptureDevice = qalcCaptureOpenDevice(NULL, 48000, AL_FORMAT_MONO16, VOIP_MAX_PACKET_SAMPLES*4); } Com_Printf( "OpenAL capture device %s.\n", (alCaptureDevice == NULL) ? "failed to open" : "opened"); diff --git a/src/qcommon/qcommon.h b/src/qcommon/qcommon.h index d71531b6..1b4a5a16 100644 --- a/src/qcommon/qcommon.h +++ b/src/qcommon/qcommon.h @@ -279,7 +279,8 @@ enum svc_ops_e { svc_EOF, // new commands, supported only by ioquake3 protocol but not legacy - svc_voip, // not wrapped in USE_VOIP, so this value is reserved. + svc_voipSpeex, // not wrapped in USE_VOIP, so this value is reserved. + svc_voipOpus, // }; @@ -295,7 +296,8 @@ enum clc_ops_e { clc_EOF, // new commands, supported only by ioquake3 protocol but not legacy - clc_voip, // not wrapped in USE_VOIP, so this value is reserved. + clc_voipSpeex, // not wrapped in USE_VOIP, so this value is reserved. + clc_voipOpus, // }; /* diff --git a/src/server/server.h b/src/server/server.h index 59b3ff8b..57d34b5b 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -45,7 +45,7 @@ typedef struct voipServerPacket_s int len; int sender; int flags; - byte data[1024]; + byte data[4000]; } voipServerPacket_t; #endif @@ -281,6 +281,7 @@ extern cvar_t *sv_banFile; #ifdef USE_VOIP extern cvar_t *sv_voip; +extern cvar_t *sv_voipProtocol; #endif diff --git a/src/server/sv_client.c b/src/server/sv_client.c index ba4392f7..dcf6311e 100644 --- a/src/server/sv_client.c +++ b/src/server/sv_client.c @@ -1200,8 +1200,8 @@ void SV_UserinfoChanged( client_t *cl ) { } #ifdef USE_VOIP - val = Info_ValueForKey(cl->userinfo, "cl_voip"); - cl->hasVoip = atoi(val); + val = Info_ValueForKey(cl->userinfo, "cl_voipProtocol"); + cl->hasVoip = !Q_stricmp( val, "opus" ); #endif // TTimo @@ -1536,7 +1536,7 @@ static qboolean SV_ShouldIgnoreVoipSender(const client_t *cl) } static -void SV_UserVoip(client_t *cl, msg_t *msg) +void SV_UserVoip(client_t *cl, msg_t *msg, qboolean ignoreData) { int sender, generation, sequence, frames, packetsize; uint8_t recips[(MAX_CLIENTS + 7) / 8]; @@ -1571,12 +1571,12 @@ void SV_UserVoip(client_t *cl, msg_t *msg) MSG_ReadData(msg, encoded, packetsize); - if (SV_ShouldIgnoreVoipSender(cl)) + if (ignoreData || SV_ShouldIgnoreVoipSender(cl)) return; // Blacklisted, disabled, etc. // !!! FIXME: see if we read past end of msg... - // !!! FIXME: reject if not speex narrowband codec. + // !!! FIXME: reject if not opus data. // !!! FIXME: decide if this is bogus data? // decide who needs this VoIP packet sent to them... @@ -1725,10 +1725,18 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) { } } while ( 1 ); + // skip legacy speex voip data + if ( c == clc_voipSpeex ) { +#ifdef USE_VOIP + SV_UserVoip( cl, msg, qtrue ); + c = MSG_ReadByte( msg ); +#endif + } + // read optional voip data - if ( c == clc_voip ) { + if ( c == clc_voipOpus ) { #ifdef USE_VOIP - SV_UserVoip( cl, msg ); + SV_UserVoip( cl, msg, qfalse ); c = MSG_ReadByte( msg ); #endif } diff --git a/src/server/sv_init.c b/src/server/sv_init.c index 30fd3936..997d58f6 100644 --- a/src/server/sv_init.c +++ b/src/server/sv_init.c @@ -646,8 +646,9 @@ void SV_Init (void) sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM ); sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO ); #ifdef USE_VOIP - sv_voip = Cvar_Get("sv_voip", "1", CVAR_SYSTEMINFO | CVAR_LATCH); + sv_voip = Cvar_Get("sv_voip", "1", CVAR_LATCH); Cvar_CheckRange(sv_voip, 0, 1, qtrue); + sv_voipProtocol = Cvar_Get("sv_voipProtocol", sv_voip->integer ? "opus" : "", CVAR_SYSTEMINFO | CVAR_ROM ); #endif Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM ); Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM ); diff --git a/src/server/sv_main.c b/src/server/sv_main.c index 77d1a35d..0c4c7f46 100644 --- a/src/server/sv_main.c +++ b/src/server/sv_main.c @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifdef USE_VOIP cvar_t *sv_voip; +cvar_t *sv_voipProtocol; #endif serverStatic_t svs; // persistant server info @@ -656,8 +657,8 @@ void SVC_Info( netadr_t from ) { Info_SetValueForKey( infostring, "pure", va("%i", sv_pure->integer ) ); #ifdef USE_VOIP - if (sv_voip->integer) { - Info_SetValueForKey( infostring, "voip", va("%i", sv_voip->integer ) ); + if (sv_voipProtocol->string && *sv_voipProtocol->string) { + Info_SetValueForKey( infostring, "voip", sv_voipProtocol->string ); } #endif diff --git a/src/server/sv_snapshot.c b/src/server/sv_snapshot.c index 71c4b86c..58136388 100644 --- a/src/server/sv_snapshot.c +++ b/src/server/sv_snapshot.c @@ -548,7 +548,7 @@ static void SV_WriteVoipToClient(client_t *cl, msg_t *msg) if (totalbytes > (msg->maxsize - msg->cursize) / 2) break; - MSG_WriteByte(msg, svc_voip); + MSG_WriteByte(msg, svc_voipOpus); MSG_WriteShort(msg, packet->sender); MSG_WriteByte(msg, (byte) packet->generation); MSG_WriteLong(msg, packet->sequence); -- cgit From 8dc446735848d849c82d3e46fcce4a9b4711dd5b Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Tue, 14 Jan 2014 21:04:50 -0600 Subject: Fix some opus_decode issues It was able to fail the assert before. I was using opus_decode wrong. --- src/client/cl_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c index 4230c04f..981d21c6 100644 --- a/src/client/cl_parse.c +++ b/src/client/cl_parse.c @@ -779,7 +779,7 @@ void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) { // tell opus that we're missing frames... for (i = 0; i < seqdiff; i++) { assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded)); - numSamples = opus_decode(clc.opusDecoder[sender], NULL, VOIP_MAX_PACKET_SAMPLES * 2, decoded + written, sizeof (decoded) - written, 0); + numSamples = opus_decode(clc.opusDecoder[sender], NULL, 0, decoded + written, VOIP_MAX_PACKET_SAMPLES, 0); if ( numSamples <= 0 ) { Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender); continue; @@ -788,7 +788,7 @@ void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) { } } - numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, sizeof (decoded) - written, 0); + numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, ARRAY_LEN(decoded) - written, 0); if ( numSamples <= 0 ) { Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender); -- cgit From ac7296d42f36891d13d7cd475f5ce46fa6ef3d63 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 15 Jan 2016 02:46:30 -0800 Subject: OpenGL2: Remove specular ambient. --- src/renderergl2/glsl/lightall_fp.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index 17dc9fca..b8f3985f 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -363,7 +363,7 @@ void main() reflectance = CalcDiffuse(diffuse.rgb, EH, NH, roughness); gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); - gl_FragColor.rgb += ambientColor * (diffuse.rgb + specular.rgb); + gl_FragColor.rgb += ambientColor * diffuse.rgb; #if defined(USE_CUBEMAP) reflectance = EnvironmentBRDF(roughness, NE, specular.rgb); -- cgit -- cgit From 970b21fbcd3d42e641807ac0c5e9a29dc21095e9 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 18 Jan 2016 04:46:01 -0800 Subject: OpenGL2: Direct state access, part 1: Texture binds --- Makefile | 1 + src/renderercommon/qgl.h | 17 +++++ src/renderergl2/tr_backend.c | 161 ++++++++++------------------------------ src/renderergl2/tr_dsa.c | 132 ++++++++++++++++++++++++++++++++ src/renderergl2/tr_dsa.h | 46 ++++++++++++ src/renderergl2/tr_extensions.c | 52 +++++++++++++ src/renderergl2/tr_image.c | 130 ++++++++++++-------------------- src/renderergl2/tr_init.c | 17 ++--- src/renderergl2/tr_local.h | 7 +- src/renderergl2/tr_main.c | 2 +- src/renderergl2/tr_shade.c | 16 ++-- src/renderergl2/tr_shadows.c | 4 +- src/renderergl2/tr_sky.c | 2 +- src/renderergl2/tr_surface.c | 4 +- 14 files changed, 355 insertions(+), 236 deletions(-) create mode 100644 src/renderergl2/tr_dsa.c create mode 100644 src/renderergl2/tr_dsa.h diff --git a/Makefile b/Makefile index 99c184b5..54809216 100644 --- a/Makefile +++ b/Makefile @@ -1538,6 +1538,7 @@ Q3R2OBJ = \ $(B)/renderergl2/tr_bsp.o \ $(B)/renderergl2/tr_cmds.o \ $(B)/renderergl2/tr_curve.o \ + $(B)/renderergl2/tr_dsa.o \ $(B)/renderergl2/tr_extramath.o \ $(B)/renderergl2/tr_extensions.o \ $(B)/renderergl2/tr_fbo.o \ diff --git a/src/renderercommon/qgl.h b/src/renderercommon/qgl.h index cc0dd6a7..232a1869 100644 --- a/src/renderercommon/qgl.h +++ b/src/renderercommon/qgl.h @@ -987,6 +987,23 @@ extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array); #define GL_VERTEX_ARRAY_BINDING_ARB 0x85B5 #endif +// GL_EXT_direct_state_access +extern GLvoid(APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, GLuint texture); +extern GLvoid(APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, GLenum pname, GLfloat param); +extern GLvoid(APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, GLenum pname, GLint param); +extern GLvoid(APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +extern GLvoid(APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +extern GLvoid(APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +extern GLvoid(APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +extern GLvoid(APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const GLvoid *data); +extern GLvoid(APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target); + #if defined(WIN32) // WGL_ARB_create_context diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 557f553b..e6dd3cfa 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "tr_local.h" +#include "tr_dsa.h" backEndData_t *backEndData; backEndState_t backEnd; @@ -36,81 +37,28 @@ static float s_flipMatrix[16] = { }; -/* -** GL_Bind -*/ -void GL_Bind( image_t *image ) { - int texnum; - - if ( !image ) { - ri.Printf( PRINT_WARNING, "GL_Bind: NULL image\n" ); - texnum = tr.defaultImage->texnum; - } else { - texnum = image->texnum; - } - - if ( r_nobind->integer && tr.dlightImage ) { // performance evaluation option - texnum = tr.dlightImage->texnum; - } - - if ( glState.currenttextures[glState.currenttmu] != texnum ) { - if ( image ) { - image->frameUsed = tr.frameCount; - } - glState.currenttextures[glState.currenttmu] = texnum; - if (image && image->flags & IMGFLAG_CUBEMAP) - qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum ); - else - qglBindTexture( GL_TEXTURE_2D, texnum ); - } -} - -/* -** GL_SelectTexture -*/ -void GL_SelectTexture( int unit ) -{ - if ( glState.currenttmu == unit ) - { - return; - } - - if (!(unit >= 0 && unit <= 31)) - ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit ); - - if (!qglActiveTextureARB) - ri.Error( ERR_DROP, "GL_SelectTexture: multitexture disabled" ); - - qglActiveTextureARB( GL_TEXTURE0_ARB + unit ); - - glState.currenttmu = unit; -} - /* ** GL_BindToTMU */ void GL_BindToTMU( image_t *image, int tmu ) { - int texnum; - int oldtmu = glState.currenttmu; + GLuint texture = (tmu == TB_COLORMAP) ? tr.defaultImage->texnum : 0; + GLenum target = GL_TEXTURE_2D; - if (!image) - texnum = 0; - else - texnum = image->texnum; - - if ( glState.currenttextures[tmu] != texnum ) { - GL_SelectTexture( tmu ); - if (image) - image->frameUsed = tr.frameCount; - glState.currenttextures[tmu] = texnum; + if (image) + { + if (image->flags & IMGFLAG_CUBEMAP) + target = GL_TEXTURE_CUBE_MAP; - if (image && (image->flags & IMGFLAG_CUBEMAP)) - qglBindTexture( GL_TEXTURE_CUBE_MAP, texnum ); - else - qglBindTexture( GL_TEXTURE_2D, texnum ); - GL_SelectTexture( oldtmu ); + image->frameUsed = tr.frameCount; + texture = image->texnum; + } + else + { + ri.Printf(PRINT_WARNING, "GL_BindToTMU: NULL image\n"); } + + GL_BindMultiTexture(GL_TEXTURE0_ARB + tmu, target, texture); } @@ -142,39 +90,6 @@ void GL_Cull( int cullType ) { glState.faceCulling = cullType; } -/* -** GL_TexEnv -*/ -void GL_TexEnv( int env ) -{ - if ( env == glState.texEnv[glState.currenttmu] ) - { - return; - } - - glState.texEnv[glState.currenttmu] = env; - - - switch ( env ) - { - case GL_MODULATE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); - break; - case GL_REPLACE: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); - break; - case GL_DECAL: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); - break; - case GL_ADD: - qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD ); - break; - default: - ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed", env ); - break; - } -} - /* ** GL_State ** @@ -856,6 +771,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * } RE_UploadCinematic (w, h, cols, rows, data, client, dirty); + GL_BindToTMU(tr.scratchImage[client], TB_COLORMAP); if ( r_speeds->integer ) { end = ri.Milliseconds(); @@ -896,23 +812,30 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * } void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { + GLuint texture; + + if (!tr.scratchImage[client]) + { + ri.Printf(PRINT_WARNING, "RE_UploadCinematic: scratch images not initialized\n"); + return; + } - GL_Bind( tr.scratchImage[client] ); + texture = tr.scratchImage[client]->texnum; // if the scratchImage isn't in the format we want, specify it as a new texture if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) { tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; - qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + qglTextureImage2D(texture, GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTextureParameterf(texture, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else { if (dirty) { // otherwise, just subimage upload it so that drivers can tell we are going to be changing // it and don't try and do a texture compression - qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); + qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data); } } } @@ -1072,11 +995,10 @@ const void *RB_DrawSurfs( const void *data ) { // If we're using multisampling, resolve the depth first FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST); } - else if (tr.renderFbo == NULL) + else if (tr.renderFbo == NULL && tr.renderDepthImage) { // If we're rendering directly to the screen, copy the depth to a texture - GL_BindToTMU(tr.renderDepthImage, 0); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); + qglCopyTextureImage2D(tr.renderDepthImage->texnum, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); } if (r_ssao->integer) @@ -1316,10 +1238,8 @@ const void *RB_DrawSurfs( const void *data ) { cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; FBO_Bind(NULL); - GL_SelectTexture(TB_CUBEMAP); - GL_BindToTMU(cubemap->image, TB_CUBEMAP); - qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); - GL_SelectTexture(0); + if (cubemap && cubemap->image) + qglGenerateTextureMipmap(cubemap->image->texnum, GL_TEXTURE_CUBE_MAP); } return (const void *)(cmd + 1); @@ -1396,7 +1316,7 @@ void RB_ShowImages( void ) { { vec4_t quadVerts[4]; - GL_Bind(image); + GL_BindToTMU(image, TB_COLORMAP); VectorSet4(quadVerts[0], x, y, 0, 1); VectorSet4(quadVerts[1], x + w, y, 0, 1); @@ -1572,21 +1492,18 @@ const void *RB_CapShadowMap(const void *data) if (cmd->map != -1) { - GL_SelectTexture(0); if (cmd->cubeSide != -1) { if (tr.shadowCubemaps[cmd->map]) { - GL_Bind(tr.shadowCubemaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); + qglCopyTextureImage2D(tr.shadowCubemaps[cmd->map]->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X + cmd->cubeSide, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); } } else { if (tr.pshadowMaps[cmd->map]) { - GL_Bind(tr.pshadowMaps[cmd->map]); - qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - ( backEnd.refdef.y + PSHADOW_MAP_SIZE ), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); + qglCopyTextureImage2D(tr.pshadowMaps[cmd->map]->texnum, GL_TEXTURE_2D, 0, GL_RGBA8, backEnd.refdef.x, glConfig.vidHeight - (backEnd.refdef.y + PSHADOW_MAP_SIZE), PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, 0); } } } @@ -1659,7 +1576,7 @@ const void *RB_PostProcess(const void *data) if (srcFbo) { - if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer) && qglActiveTextureARB) + if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer)) { autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer; RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure); @@ -1775,7 +1692,7 @@ const void *RB_ExportCubemaps(const void *data) { char filename[MAX_QPATH]; cubemap_t *cubemap = &tr.cubemaps[i]; - char *p = cubemapPixels; + byte *p = cubemapPixels; for (j = 0; j < 6; j++) { diff --git a/src/renderergl2/tr_dsa.c b/src/renderergl2/tr_dsa.c new file mode 100644 index 00000000..55a731d9 --- /dev/null +++ b/src/renderergl2/tr_dsa.c @@ -0,0 +1,132 @@ +/* +=========================================================================== +Copyright (C) 2016 James Canete + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +=========================================================================== +*/ + +#include "tr_local.h" + +#include "tr_dsa.h" + +static struct +{ + GLuint textures[NUM_TEXTURE_BUNDLES]; + GLenum texunit; +} +glDsaState; + +void GL_BindNullTextures() +{ + int i; + + if (glRefConfig.directStateAccess) + { + for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) + { + qglBindMultiTexture(GL_TEXTURE0_ARB + i, GL_TEXTURE_2D, 0); + glDsaState.textures[i] = 0; + } + } + else + { + for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) + { + qglActiveTextureARB(GL_TEXTURE0_ARB + i); + qglBindTexture(GL_TEXTURE_2D, 0); + glDsaState.textures[i] = 0; + } + + qglActiveTextureARB(GL_TEXTURE0_ARB); + glDsaState.texunit = GL_TEXTURE0_ARB; + } +} + +void GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) +{ + GLuint tmu = texunit - GL_TEXTURE0_ARB; + + if (glDsaState.textures[tmu] == texture) + return; + + qglBindMultiTexture(texunit, target, texture); + glDsaState.textures[tmu] = texture; +} + +GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) +{ + if (glDsaState.texunit != texunit) + { + qglActiveTextureARB(texunit); + glDsaState.texunit = texunit; + } + + qglBindTexture(target, texture); +} + +GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglTexParameterf(target, pname, param); +} + +GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglTexParameteri(target, pname, param); +} + +GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); +} + +GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); +} + +GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglCopyTexImage2D(target, level, internalformat, x, y, width, height, border); +} + +GLvoid APIENTRY GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglCompressedTexImage2DARB(target, level, internalformat, width, height, border, imageSize, data); +} + +GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const GLvoid *data) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglCompressedTexSubImage2DARB(target, level, xoffset, yoffset, width, height, format, imageSize, data); +} + +GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target) +{ + GL_BindMultiTexture(glDsaState.texunit, target, texture); + qglGenerateMipmapEXT(target); +} diff --git a/src/renderergl2/tr_dsa.h b/src/renderergl2/tr_dsa.h new file mode 100644 index 00000000..c166b9f3 --- /dev/null +++ b/src/renderergl2/tr_dsa.h @@ -0,0 +1,46 @@ +/* +=========================================================================== +Copyright (C) 2016 James Canete + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +=========================================================================== +*/ + +#ifndef __TR_DSA_H__ +#define __TR_DSA_H__ + +#include "../renderercommon/qgl.h" + +void GL_BindNullTextures(void); +void GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture); + +GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture); +GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param); +GLvoid APIENTRY GLDSA_TextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param); +GLvoid APIENTRY GLDSA_TextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLvoid APIENTRY GLDSA_TextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLvoid APIENTRY GLDSA_CopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLvoid APIENTRY GLDSA_CompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const GLvoid *data); + +GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target); + +#endif diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c index 2c1407b2..abafbf97 100644 --- a/src/renderergl2/tr_extensions.c +++ b/src/renderergl2/tr_extensions.c @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif #include "tr_local.h" +#include "tr_dsa.h" // GL_EXT_draw_range_elements void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); @@ -184,6 +185,23 @@ void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays); void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays); GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array); +// GL_EXT_direct_state_access +GLvoid (APIENTRY * qglBindMultiTexture)(GLenum texunit, GLenum target, GLuint texture); +GLvoid (APIENTRY * qglTextureParameterf)(GLuint texture, GLenum target, GLenum pname, GLfloat param); +GLvoid (APIENTRY * qglTextureParameteri)(GLuint texture, GLenum target, GLenum pname, GLint param); +GLvoid (APIENTRY * qglTextureImage2D)(GLuint texture, GLenum target, GLint level, GLint internalformat, + GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +GLvoid (APIENTRY * qglTextureSubImage2D)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +GLvoid (APIENTRY * qglCopyTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLvoid (APIENTRY * qglCompressedTextureImage2D)(GLuint texture, GLenum target, GLint level, GLenum internalformat, + GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); +GLvoid (APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, + GLsizei imageSize, const GLvoid *data); +GLvoid (APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target); + static qboolean GLimp_HaveExtension(const char *ext) { const char *ptr = Q_stristr( glConfig.extensions_string, ext ); @@ -750,4 +768,38 @@ void GLimp_InitExtraExtensions() ri.Printf(PRINT_ALL, result[2], extension); } + // GL_EXT_direct_state_access + extension = "GL_EXT_direct_state_access"; + qglBindMultiTexture = GLDSA_BindMultiTexture; + qglTextureParameterf = GLDSA_TextureParameterf; + qglTextureParameteri = GLDSA_TextureParameteri; + qglTextureImage2D = GLDSA_TextureImage2D; + qglTextureSubImage2D = GLDSA_TextureSubImage2D; + qglCopyTextureImage2D = GLDSA_CopyTextureImage2D; + qglCompressedTextureImage2D = GLDSA_CompressedTextureImage2D; + qglCompressedTextureSubImage2D = GLDSA_CompressedTextureSubImage2D; + qglGenerateTextureMipmap = GLDSA_GenerateTextureMipmap; + glRefConfig.directStateAccess = qfalse; + if (GLimp_HaveExtension(extension)) + { + if (r_ext_direct_state_access->integer) + { + glRefConfig.directStateAccess = qtrue; + qglBindMultiTexture = (void *)SDL_GL_GetProcAddress("glBindMultiTextureEXT"); + qglTextureParameterf = (void *)SDL_GL_GetProcAddress("glTextureParameterfEXT"); + qglTextureParameteri = (void *)SDL_GL_GetProcAddress("glTextureParameteriEXT"); + qglTextureImage2D = (void *)SDL_GL_GetProcAddress("glTextureImage2DEXT"); + qglTextureSubImage2D = (void *)SDL_GL_GetProcAddress("glTextureSubImage2DEXT"); + qglCopyTextureImage2D = (void *)SDL_GL_GetProcAddress("glCopyTextureImage2DEXT"); + qglCompressedTextureImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureImage2DEXT"); + qglCompressedTextureSubImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureSubImage2DEXT"); + qglGenerateTextureMipmap = (void *)SDL_GL_GetProcAddress("glGenerateTextureMipmapEXT"); + } + + ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess ? 1 : 0], extension); + } + else + { + ri.Printf(PRINT_ALL, result[2], extension); + } } diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index d01f42c4..aade799e 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_image.c #include "tr_local.h" +#include "tr_dsa.h" + static byte s_intensitytable[256]; static unsigned char s_gammatable[256]; @@ -115,9 +117,8 @@ void GL_TextureMode( const char *string ) { for ( i = 0 ; i < tr.numImages ; i++ ) { glt = tr.images[ i ]; if ( glt->flags & IMGFLAG_MIPMAP ) { - GL_Bind (glt); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); + qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } } } @@ -1818,7 +1819,7 @@ static void CompressMonoBlock(byte outdata[8], const byte indata[16]) } } -static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int mip) +static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width, int height, int mip) { int wBlocks, hBlocks, y, x, size; byte *compressedData, *p; @@ -1858,13 +1859,13 @@ static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int } } - qglCompressedTexImage2DARB(GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData); + qglCompressedTextureImage2D(texture, GL_TEXTURE_2D, mip, GL_COMPRESSED_RG_RGTC2, width, height, 0, size, compressedData); ri.Hunk_FreeTempMemory(compressedData); } -static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) +static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) { int dataFormat, dataType; qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); @@ -1924,9 +1925,9 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; if (subtexture) - qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data); + qglCompressedTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data); else - qglCompressedTexImage2DARB(GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, size, data); + qglCompressedTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, size, data); x >>= 1; y >>= 1; @@ -1958,13 +1959,13 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei } if ( subtexture ) - qglTexSubImage2D( GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); + qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); else { if (rgtc) - RawImage_UploadToRgtc2Texture(data, width, height, 0); + RawImage_UploadToRgtc2Texture(texture, data, width, height, 0); else - qglTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data); + qglTextureImage2D(texture, GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data); } if (flags & IMGFLAG_MIPMAP) @@ -1992,14 +1993,14 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei { x >>= 1; y >>= 1; - qglTexSubImage2D( GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data ); + qglTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data ); } else { if (rgtc) - RawImage_UploadToRgtc2Texture(data, width, height, miplevel); + RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel); else - qglTexImage2D(GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); + qglTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); } } } @@ -2028,14 +2029,14 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic if (!data) { RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL); - RawImage_UploadTexture(NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); goto done; } else if (!subtexture) { if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) { - RawImage_UploadTexture(data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); goto done; } notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer); @@ -2075,12 +2076,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic if (subtexture) { // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped - RawImage_UploadTexture(data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue); + RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue); GL_CheckErrors(); return; } - RawImage_UploadTexture(data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); done: @@ -2090,19 +2091,19 @@ done: if (mipmap) { if ( glConfig.textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp( 1, glConfig.maxAnisotropy, r_ext_max_anisotropy->integer ) ); + qglTextureParameteri( image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, + (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { if ( glConfig.textureFilterAnisotropic ) - qglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); + qglTextureParameteri(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } // Fix for sampling depth buffer on old nVidia cards @@ -2113,9 +2114,9 @@ done: case GL_DEPTH_COMPONENT16_ARB: case GL_DEPTH_COMPONENT24_ARB: case GL_DEPTH_COMPONENT32_ARB: - qglTexParameterf(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; default: break; @@ -2178,46 +2179,32 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe image->internalFormat = internalFormat; - - // lightmaps are always allocated on TMU 1 - if ( qglActiveTextureARB && isLightmap ) { - image->TMU = 1; - } else { - image->TMU = 0; - } - - if ( qglActiveTextureARB ) { - GL_SelectTexture( image->TMU ); - } - - GL_Bind(image); - if (image->flags & IMGFLAG_CUBEMAP) { - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (image->flags & IMGFLAG_MIPMAP) { - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); + qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); if (image->flags & IMGFLAG_MIPMAP) - qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); + qglGenerateTextureMipmap(image->texnum, GL_TEXTURE_CUBE_MAP); image->uploadWidth = width; image->uploadHeight = height; @@ -2226,12 +2213,10 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe { Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode); + qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode); } - GL_SelectTexture( 0 ); - hash = generateHashValue(name); image->next = hashTable[hash]; hashTable[hash] = image; @@ -2255,15 +2240,7 @@ image_t *R_CreateImage(const char *name, byte *pic, int width, int height, imgTy void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height ) { - if (qglActiveTextureARB) { - GL_SelectTexture(image->TMU); - } - - GL_Bind(image); - Upload32(pic, x, y, width, height, GL_RGBA8, 0, image); - - GL_SelectTexture(0); } //=================================================================== @@ -2830,11 +2807,10 @@ void R_CreateBuiltinImages( void ) { for ( x = 0; x < 4; x++) { tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); - GL_Bind(tr.sunShadowDepthImage[x]); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); - qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); @@ -2947,15 +2923,7 @@ void R_DeleteTextures( void ) { tr.numImages = 0; - Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) ); - if ( qglActiveTextureARB ) { - GL_SelectTexture( 1 ); - qglBindTexture( GL_TEXTURE_2D, 0 ); - GL_SelectTexture( 0 ); - qglBindTexture( GL_TEXTURE_2D, 0 ); - } else { - qglBindTexture( GL_TEXTURE_2D, 0 ); - } + GL_BindNullTextures(); } /* diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index bf05e210..05b00465 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" +#include "tr_dsa.h" + glconfig_t glConfig; glRefConfig_t glRefConfig; qboolean textureFilterAnisotropic = qfalse; @@ -105,6 +107,7 @@ cvar_t *r_ext_framebuffer_multisample; cvar_t *r_arb_seamless_cube_map; cvar_t *r_arb_vertex_type_2_10_10_10_rev; cvar_t *r_arb_vertex_array_object; +cvar_t *r_ext_direct_state_access; cvar_t *r_mergeMultidraws; cvar_t *r_mergeLeafSurfaces; @@ -765,7 +768,7 @@ void R_ScreenShotJPEG_f (void) { R_ExportCubemaps ================== */ -void R_ExportCubemaps() +void R_ExportCubemaps(void) { exportCubemapsCommand_t *cmd; @@ -883,19 +886,10 @@ void GL_SetDefaultState( void ) qglColor4f (1,1,1,1); - // initialize downstream texture unit if we're running - // in a multitexture environment - if ( qglActiveTextureARB ) { - GL_SelectTexture( 1 ); - GL_TextureMode( r_textureMode->string ); - GL_TexEnv( GL_MODULATE ); - qglDisable( GL_TEXTURE_2D ); - GL_SelectTexture( 0 ); - } + GL_BindNullTextures(); qglEnable(GL_TEXTURE_2D); GL_TextureMode( r_textureMode->string ); - GL_TexEnv( GL_MODULATE ); //qglShadeModel( GL_SMOOTH ); qglDepthFunc( GL_LEQUAL ); @@ -1108,6 +1102,7 @@ void R_Register( void ) r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH); r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH); r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH); + r_ext_direct_state_access = ri.Cvar_Get("r_ext_direct_state_access", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", "0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 72f11989..0dd61674 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1352,8 +1352,6 @@ typedef struct { // the renderer front end should never modify glstate_t typedef struct { - int currenttextures[NUM_TEXTURE_BUNDLES]; - int currenttmu; qboolean finishCalled; int texEnv[2]; int faceCulling; @@ -1421,6 +1419,7 @@ typedef struct { qboolean floatLightmap; qboolean vertexArrayObject; + qboolean directStateAccess; } glRefConfig_t; @@ -1720,6 +1719,7 @@ extern cvar_t *r_ext_framebuffer_multisample; extern cvar_t *r_arb_seamless_cube_map; extern cvar_t *r_arb_vertex_type_2_10_10_10_rev; extern cvar_t *r_arb_vertex_array_object; +extern cvar_t *r_ext_direct_state_access; extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_singleShader; // make most world faces use default shader @@ -1884,17 +1884,14 @@ void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, /* ** GL wrapper/helper functions */ -void GL_Bind( image_t *image ); void GL_BindToTMU( image_t *image, int tmu ); void GL_SetDefaultState (void); -void GL_SelectTexture( int unit ); void GL_TextureMode( const char *string ); void GL_CheckErrs( char *file, int line ); #define GL_CheckErrors(...) GL_CheckErrs(__FILE__, __LINE__) void GL_State( unsigned long stateVector ); void GL_SetProjectionMatrix(mat4_t matrix); void GL_SetModelviewMatrix(mat4_t matrix); -void GL_TexEnv( int env ); void GL_Cull( int cullType ); #define GLS_SRCBLEND_ZERO 0x00000001 diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index 14d18755..63fea5ac 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -2031,7 +2031,7 @@ void R_DebugGraphics( void ) { R_IssuePendingRenderCommands(); - GL_Bind( tr.whiteImage); + GL_BindToTMU(tr.whiteImage, TB_COLORMAP); GL_Cull( CT_FRONT_SIDED ); ri.CM_DrawDebugSurface( R_DebugPolygon ); } diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index 04b62517..f4d32a5e 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -102,11 +102,9 @@ static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) { int index; if ( bundle->isVideoMap ) { - int oldtmu = glState.currenttmu; - GL_SelectTexture(tmu); ri.CIN_RunCinematic(bundle->videoMapHandle); ri.CIN_UploadCinematic(bundle->videoMapHandle); - GL_SelectTexture(oldtmu); + GL_BindToTMU(tr.scratchImage[bundle->videoMapHandle], tmu); return; } @@ -137,7 +135,7 @@ Draws triangle outlines for debugging ================ */ static void DrawTris (shaderCommands_t *input) { - GL_Bind( tr.whiteImage ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); qglDepthRange( 0, 0 ); @@ -415,7 +413,7 @@ static void ProjectDlightTexture( void ) { vector[3] = scale; GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector); - GL_Bind( tr.dlightImage ); + GL_BindToTMU( tr.dlightImage, TB_COLORMAP ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered @@ -863,11 +861,7 @@ static void ForwardDlight( void ) { } if (r_dlightMode->integer >= 2) - { - GL_SelectTexture(TB_SHADOWMAP); - GL_Bind(tr.shadowCubemaps[l]); - GL_SelectTexture(0); - } + GL_BindToTMU(tr.shadowCubemaps[l], TB_SHADOWMAP); ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); @@ -1267,7 +1261,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) if ( backEnd.depthFill ) { if (!(pStage->stateBits & GLS_ATEST_BITS)) - GL_BindToTMU( tr.whiteImage, 0 ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP ); } diff --git a/src/renderergl2/tr_shadows.c b/src/renderergl2/tr_shadows.c index fdb39091..33bf4bdc 100644 --- a/src/renderergl2/tr_shadows.c +++ b/src/renderergl2/tr_shadows.c @@ -207,7 +207,7 @@ void RB_ShadowTessEnd( void ) { // draw the silhouette edges - GL_Bind( tr.whiteImage ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor3f( 0.2f, 0.2f, 0.2f ); @@ -257,7 +257,7 @@ void RB_ShadowFinish( void ) { qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); - GL_Bind( tr.whiteImage ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); qglLoadIdentity (); diff --git a/src/renderergl2/tr_sky.c b/src/renderergl2/tr_sky.c index ae1dc2ab..3545a973 100644 --- a/src/renderergl2/tr_sky.c +++ b/src/renderergl2/tr_sky.c @@ -375,7 +375,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max //tess.numIndexes = 0; tess.firstIndex = tess.numIndexes; - GL_Bind( image ); + GL_BindToTMU( image, TB_COLORMAP ); GL_Cull( CT_TWO_SIDED ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) diff --git a/src/renderergl2/tr_surface.c b/src/renderergl2/tr_surface.c index e6146eef..92802f38 100644 --- a/src/renderergl2/tr_surface.c +++ b/src/renderergl2/tr_surface.c @@ -576,7 +576,7 @@ static void RB_SurfaceBeam( void ) VectorAdd( start_points[i], direction, end_points[i] ); } - GL_Bind( tr.whiteImage ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); @@ -1519,7 +1519,7 @@ Draws x/y/z lines from the origin for orientation debugging static void RB_SurfaceAxis( void ) { // FIXME: implement this #if 0 - GL_Bind( tr.whiteImage ); + GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_DEFAULT ); qglLineWidth( 3 ); qglBegin( GL_LINES ); -- cgit From 95633de9cb7414060e6d7c1102dd85385f203311 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 18 Jan 2016 23:30:36 -0800 Subject: OpenGL2: Direct state access, part 2: Uniforms. --- src/renderercommon/qgl.h | 14 +++++++ src/renderergl2/tr_dsa.c | 71 +++++++++++++++++++++++++++++++++- src/renderergl2/tr_dsa.h | 19 +++++++++- src/renderergl2/tr_extensions.c | 32 ++++++++++++++++ src/renderergl2/tr_glsl.c | 84 +++++++---------------------------------- src/renderergl2/tr_init.c | 3 +- src/renderergl2/tr_local.h | 2 - 7 files changed, 147 insertions(+), 78 deletions(-) diff --git a/src/renderercommon/qgl.h b/src/renderercommon/qgl.h index 232a1869..f4d30bf0 100644 --- a/src/renderercommon/qgl.h +++ b/src/renderercommon/qgl.h @@ -1004,6 +1004,20 @@ extern GLvoid(APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum GLsizei imageSize, const GLvoid *data); extern GLvoid(APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target); +extern GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, GLint v0); +extern GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, GLfloat v0); +extern GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1); +extern GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2); +extern GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +extern GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location, + GLsizei count, const GLfloat *value); +extern GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location, + GLsizei count, GLboolean transpose, + const GLfloat *value); + #if defined(WIN32) // WGL_ARB_create_context diff --git a/src/renderergl2/tr_dsa.c b/src/renderergl2/tr_dsa.c index 55a731d9..9472bb40 100644 --- a/src/renderergl2/tr_dsa.c +++ b/src/renderergl2/tr_dsa.c @@ -26,6 +26,8 @@ static struct { GLuint textures[NUM_TEXTURE_BUNDLES]; GLenum texunit; + + GLuint program; } glDsaState; @@ -55,15 +57,16 @@ void GL_BindNullTextures() } } -void GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) +int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) { GLuint tmu = texunit - GL_TEXTURE0_ARB; if (glDsaState.textures[tmu] == texture) - return; + return 0; qglBindMultiTexture(texunit, target, texture); glDsaState.textures[tmu] = texture; + return 1; } GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) @@ -130,3 +133,67 @@ GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target) GL_BindMultiTexture(glDsaState.texunit, target, texture); qglGenerateMipmapEXT(target); } + +void GL_BindNullProgram() +{ + qglUseProgramObjectARB(0); + glDsaState.program = 0; +} + +int GL_UseProgramObject(GLuint program) +{ + if (glDsaState.program == program) + return 0; + + qglUseProgramObjectARB(program); + glDsaState.program = program; + return 1; +} + +GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint v0) +{ + GL_UseProgramObject(program); + qglUniform1iARB(location, v0); +} + +GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat v0) +{ + GL_UseProgramObject(program); + qglUniform1fARB(location, v0); +} + +GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location, + GLfloat v0, GLfloat v1) +{ + GL_UseProgramObject(program); + qglUniform2fARB(location, v0, v1); +} + +GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2) +{ + GL_UseProgramObject(program); + qglUniform3fARB(location, v0, v1, v2); +} + +GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) +{ + GL_UseProgramObject(program); + qglUniform4fARB(location, v0, v1, v2, v3); +} + +GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location, + GLsizei count, const GLfloat *value) +{ + GL_UseProgramObject(program); + qglUniform1fvARB(location, count, value); +} + +GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location, + GLsizei count, GLboolean transpose, + const GLfloat *value) +{ + GL_UseProgramObject(program); + qglUniformMatrix4fvARB(location, count, transpose, value); +} diff --git a/src/renderergl2/tr_dsa.h b/src/renderergl2/tr_dsa.h index c166b9f3..164ab065 100644 --- a/src/renderergl2/tr_dsa.h +++ b/src/renderergl2/tr_dsa.h @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "../renderercommon/qgl.h" void GL_BindNullTextures(void); -void GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture); +int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture); GLvoid APIENTRY GLDSA_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture); GLvoid APIENTRY GLDSA_TextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param); @@ -43,4 +43,21 @@ GLvoid APIENTRY GLDSA_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLvoid APIENTRY GLDSA_GenerateTextureMipmap(GLuint texture, GLenum target); +void GL_BindNullProgram(void); +int GL_UseProgramObject(GLuint program); + +GLvoid APIENTRY GLDSA_ProgramUniform1i(GLuint program, GLint location, GLint v0); +GLvoid APIENTRY GLDSA_ProgramUniform1f(GLuint program, GLint location, GLfloat v0); +GLvoid APIENTRY GLDSA_ProgramUniform2f(GLuint program, GLint location, + GLfloat v0, GLfloat v1); +GLvoid APIENTRY GLDSA_ProgramUniform3f(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2); +GLvoid APIENTRY GLDSA_ProgramUniform4f(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLvoid APIENTRY GLDSA_ProgramUniform1fv(GLuint program, GLint location, + GLsizei count, const GLfloat *value); +GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location, + GLsizei count, GLboolean transpose, + const GLfloat *value); + #endif diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c index abafbf97..bb668da2 100644 --- a/src/renderergl2/tr_extensions.c +++ b/src/renderergl2/tr_extensions.c @@ -202,6 +202,20 @@ GLvoid (APIENTRY * qglCompressedTextureSubImage2D)(GLuint texture, GLenum target GLsizei imageSize, const GLvoid *data); GLvoid (APIENTRY * qglGenerateTextureMipmap)(GLuint texture, GLenum target); +GLvoid(APIENTRY * qglProgramUniform1i)(GLuint program, GLint location, GLint v0); +GLvoid(APIENTRY * qglProgramUniform1f)(GLuint program, GLint location, GLfloat v0); +GLvoid(APIENTRY * qglProgramUniform2f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1); +GLvoid(APIENTRY * qglProgramUniform3f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2); +GLvoid(APIENTRY * qglProgramUniform4f)(GLuint program, GLint location, + GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLvoid(APIENTRY * qglProgramUniform1fv)(GLuint program, GLint location, + GLsizei count, const GLfloat *value); +GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location, + GLsizei count, GLboolean transpose, + const GLfloat *value); + static qboolean GLimp_HaveExtension(const char *ext) { const char *ptr = Q_stristr( glConfig.extensions_string, ext ); @@ -770,6 +784,7 @@ void GLimp_InitExtraExtensions() // GL_EXT_direct_state_access extension = "GL_EXT_direct_state_access"; + qglBindMultiTexture = GLDSA_BindMultiTexture; qglTextureParameterf = GLDSA_TextureParameterf; qglTextureParameteri = GLDSA_TextureParameteri; @@ -779,6 +794,15 @@ void GLimp_InitExtraExtensions() qglCompressedTextureImage2D = GLDSA_CompressedTextureImage2D; qglCompressedTextureSubImage2D = GLDSA_CompressedTextureSubImage2D; qglGenerateTextureMipmap = GLDSA_GenerateTextureMipmap; + + qglProgramUniform1i = GLDSA_ProgramUniform1i; + qglProgramUniform1f = GLDSA_ProgramUniform1f; + qglProgramUniform2f = GLDSA_ProgramUniform2f; + qglProgramUniform3f = GLDSA_ProgramUniform3f; + qglProgramUniform4f = GLDSA_ProgramUniform4f; + qglProgramUniform1fv = GLDSA_ProgramUniform1fv; + qglProgramUniformMatrix4fv = GLDSA_ProgramUniformMatrix4fv; + glRefConfig.directStateAccess = qfalse; if (GLimp_HaveExtension(extension)) { @@ -794,6 +818,14 @@ void GLimp_InitExtraExtensions() qglCompressedTextureImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureImage2DEXT"); qglCompressedTextureSubImage2D = (void *)SDL_GL_GetProcAddress("glCompressedTextureSubImage2DEXT"); qglGenerateTextureMipmap = (void *)SDL_GL_GetProcAddress("glGenerateTextureMipmapEXT"); + + qglProgramUniform1i = (void *)SDL_GL_GetProcAddress("glProgramUniform1iEXT"); + qglProgramUniform1f = (void *)SDL_GL_GetProcAddress("glProgramUniform1fEXT"); + qglProgramUniform2f = (void *)SDL_GL_GetProcAddress("glProgramUniform2fEXT"); + qglProgramUniform3f = (void *)SDL_GL_GetProcAddress("glProgramUniform3fEXT"); + qglProgramUniform4f = (void *)SDL_GL_GetProcAddress("glProgramUniform4fEXT"); + qglProgramUniform1fv = (void *)SDL_GL_GetProcAddress("glProgramUniform1fvEXT"); + qglProgramUniformMatrix4fv = (void *)SDL_GL_GetProcAddress("glProgramUniformMatrix4fvEXT"); } ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess ? 1 : 0], extension); diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index 14e20105..eaa7c8f5 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -22,7 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_glsl.c #include "tr_local.h" -void GLSL_BindNullProgram(void); +#include "tr_dsa.h" extern const char *fallbackShader_bokeh_vp; extern const char *fallbackShader_bokeh_fp; @@ -482,11 +482,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program) GLenum type; char uniformName[1000]; - // install the executables in the program object as part of current state. - qglUseProgramObjectARB(program); - - // check for GL Errors - // query the number of active uniforms qglGetObjectParameterivARB(program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &count); @@ -497,8 +492,6 @@ static void GLSL_ShowProgramUniforms(GLhandleARB program) ri.Printf(PRINT_DEVELOPER, "active uniform: '%s'\n", uniformName); } - - qglUseProgramObjectARB(0); } static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int attribs, const char *vpCode, const char *fpCode) @@ -703,7 +696,7 @@ void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value) *compare = value; - qglUniform1iARB(uniforms[uniformNum], value); + qglProgramUniform1i(program->program, uniforms[uniformNum], value); } void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value) @@ -727,7 +720,7 @@ void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat valu *compare = value; - qglUniform1fARB(uniforms[uniformNum], value); + qglProgramUniform1f(program->program, uniforms[uniformNum], value); } void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t v) @@ -752,7 +745,7 @@ void GLSL_SetUniformVec2(shaderProgram_t *program, int uniformNum, const vec2_t compare[0] = v[0]; compare[1] = v[1]; - qglUniform2fARB(uniforms[uniformNum], v[0], v[1]); + qglProgramUniform2f(program->program, uniforms[uniformNum], v[0], v[1]); } void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t v) @@ -776,7 +769,7 @@ void GLSL_SetUniformVec3(shaderProgram_t *program, int uniformNum, const vec3_t VectorCopy(v, compare); - qglUniform3fARB(uniforms[uniformNum], v[0], v[1], v[2]); + qglProgramUniform3f(program->program, uniforms[uniformNum], v[0], v[1], v[2]); } void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t v) @@ -800,7 +793,7 @@ void GLSL_SetUniformVec4(shaderProgram_t *program, int uniformNum, const vec4_t VectorCopy4(v, compare); - qglUniform4fARB(uniforms[uniformNum], v[0], v[1], v[2], v[3]); + qglProgramUniform4f(program->program, uniforms[uniformNum], v[0], v[1], v[2], v[3]); } void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_t v) @@ -824,7 +817,7 @@ void GLSL_SetUniformFloat5(shaderProgram_t *program, int uniformNum, const vec5_ VectorCopy5(v, compare); - qglUniform1fvARB(uniforms[uniformNum], 5, v); + qglProgramUniform1fv(program->program, uniforms[uniformNum], 5, v); } void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t matrix) @@ -848,7 +841,7 @@ void GLSL_SetUniformMat4(shaderProgram_t *program, int uniformNum, const mat4_t Mat4Copy(matrix, compare); - qglUniformMatrix4fvARB(uniforms[uniformNum], 1, GL_FALSE, matrix); + qglProgramUniformMatrix4fv(program->program, uniforms[uniformNum], 1, GL_FALSE, matrix); } void GLSL_DeleteGPUShader(shaderProgram_t *program) @@ -925,10 +918,8 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.genericShader[i]); - qglUseProgramObjectARB(tr.genericShader[i].program); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.genericShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.genericShader[i]); @@ -945,9 +936,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.textureColorShader); - qglUseProgramObjectARB(tr.textureColorShader.program); GLSL_SetUniformInt(&tr.textureColorShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.textureColorShader); @@ -993,9 +982,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.dlightShader[i]); - qglUseProgramObjectARB(tr.dlightShader[i].program); GLSL_SetUniformInt(&tr.dlightShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.dlightShader[i]); @@ -1123,7 +1110,6 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.lightallShader[i]); - qglUseProgramObjectARB(tr.lightallShader[i].program); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_DIFFUSEMAP, TB_DIFFUSEMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_LIGHTMAP, TB_LIGHTMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_NORMALMAP, TB_NORMALMAP); @@ -1131,7 +1117,6 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SPECULARMAP, TB_SPECULARMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.lightallShader[i], UNIFORM_CUBEMAP, TB_CUBEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.lightallShader[i]); @@ -1164,9 +1149,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.pshadowShader); - qglUseProgramObjectARB(tr.pshadowShader.program); GLSL_SetUniformInt(&tr.pshadowShader, UNIFORM_SHADOWMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.pshadowShader); @@ -1183,9 +1166,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.down4xShader); - qglUseProgramObjectARB(tr.down4xShader.program); GLSL_SetUniformInt(&tr.down4xShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.down4xShader); @@ -1202,9 +1183,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.bokehShader); - qglUseProgramObjectARB(tr.bokehShader.program); GLSL_SetUniformInt(&tr.bokehShader, UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.bokehShader); @@ -1221,10 +1200,8 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.tonemapShader); - qglUseProgramObjectARB(tr.tonemapShader.program); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_TEXTUREMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.tonemapShader, UNIFORM_LEVELSMAP, TB_LEVELSMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.tonemapShader); @@ -1246,9 +1223,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.calclevels4xShader[i]); - qglUseProgramObjectARB(tr.calclevels4xShader[i].program); GLSL_SetUniformInt(&tr.calclevels4xShader[i], UNIFORM_TEXTUREMAP, TB_DIFFUSEMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.calclevels4xShader[i]); @@ -1279,13 +1254,11 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.shadowmaskShader); - qglUseProgramObjectARB(tr.shadowmaskShader.program); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.shadowmaskShader); @@ -1302,9 +1275,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.ssaoShader); - qglUseProgramObjectARB(tr.ssaoShader.program); GLSL_SetUniformInt(&tr.ssaoShader, UNIFORM_SCREENDEPTHMAP, TB_COLORMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.ssaoShader); @@ -1329,10 +1300,8 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.depthBlurShader[i]); - qglUseProgramObjectARB(tr.depthBlurShader[i].program); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENIMAGEMAP, TB_COLORMAP); GLSL_SetUniformInt(&tr.depthBlurShader[i], UNIFORM_SCREENDEPTHMAP, TB_LIGHTMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.depthBlurShader[i]); @@ -1350,9 +1319,7 @@ void GLSL_InitGPUShaders(void) GLSL_InitUniforms(&tr.testcubeShader); - qglUseProgramObjectARB(tr.testcubeShader.program); GLSL_SetUniformInt(&tr.testcubeShader, UNIFORM_TEXTUREMAP, TB_COLORMAP); - qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.testcubeShader); @@ -1376,7 +1343,7 @@ void GLSL_ShutdownGPUShaders(void) for (i = 0; i < ATTR_INDEX_COUNT; i++) qglDisableVertexAttribArrayARB(i); - GLSL_BindNullProgram(); + GL_BindNullProgram(); for ( i = 0; i < GENERICDEF_COUNT; i++) GLSL_DeleteGPUShader(&tr.genericShader[i]); @@ -1406,47 +1373,22 @@ void GLSL_ShutdownGPUShaders(void) for ( i = 0; i < 2; i++) GLSL_DeleteGPUShader(&tr.depthBlurShader[i]); - - glState.currentProgram = 0; - qglUseProgramObjectARB(0); } void GLSL_BindProgram(shaderProgram_t * program) { - if(!program) - { - GLSL_BindNullProgram(); - return; - } + GLuint programObject = program ? program->program : 0; + char *name = program ? program->name : "NULL"; if(r_logFile->integer) { // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- GL_BindProgram( %s ) ---\n", program->name)); + GLimp_LogComment(va("--- GLSL_BindProgram( %s ) ---\n", name)); } - if(glState.currentProgram != program) - { - qglUseProgramObjectARB(program->program); - glState.currentProgram = program; + if (GL_UseProgramObject(programObject)) backEnd.pc.c_glslShaderBinds++; - } -} - - -void GLSL_BindNullProgram(void) -{ - if(r_logFile->integer) - { - GLimp_LogComment("--- GL_BindNullProgram ---\n"); - } - - if(glState.currentProgram) - { - qglUseProgramObjectARB(0); - glState.currentProgram = NULL; - } } diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 05b00465..8e27c620 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -902,8 +902,7 @@ void GL_SetDefaultState( void ) glState.faceCulling = CT_TWO_SIDED; glState.faceCullFront = qtrue; - glState.currentProgram = 0; - qglUseProgramObjectARB(0); + GL_BindNullProgram(); if (glRefConfig.vertexArrayObject) qglBindVertexArrayARB(0); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 0dd61674..f56d5f51 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1361,7 +1361,6 @@ typedef struct { float vertexAttribsInterpolation; qboolean vertexAnimation; uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise - shaderProgram_t *currentProgram; FBO_t *currentFBO; vao_t *currentVao; mat4_t modelview; @@ -2215,7 +2214,6 @@ void GLSL_InitGPUShaders(void); void GLSL_ShutdownGPUShaders(void); void GLSL_VertexAttribPointers(uint32_t attribBits); void GLSL_BindProgram(shaderProgram_t * program); -void GLSL_BindNullProgram(void); void GLSL_SetUniformInt(shaderProgram_t *program, int uniformNum, GLint value); void GLSL_SetUniformFloat(shaderProgram_t *program, int uniformNum, GLfloat value); -- cgit From 1adb3a37252948d4e3bc65fafbb3438cb027458f Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 20 Jan 2016 06:32:50 -0800 Subject: OpenGL2: Direct state access, part 3: Framebuffers. --- src/renderercommon/qgl.h | 14 ++ src/renderergl2/tr_dsa.c | 85 ++++++++++++ src/renderergl2/tr_dsa.h | 17 +++ src/renderergl2/tr_extensions.c | 25 ++++ src/renderergl2/tr_fbo.c | 287 +++++++--------------------------------- src/renderergl2/tr_init.c | 1 + 6 files changed, 191 insertions(+), 238 deletions(-) diff --git a/src/renderercommon/qgl.h b/src/renderercommon/qgl.h index f4d30bf0..bf48cc62 100644 --- a/src/renderercommon/qgl.h +++ b/src/renderercommon/qgl.h @@ -1018,6 +1018,20 @@ extern GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint locat GLsizei count, GLboolean transpose, const GLfloat *value); +extern GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer, + GLenum internalformat, GLsizei width, GLsizei height); + +extern GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint renderbuffer, + GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +extern GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target); +extern GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer, + GLenum attachment, GLenum textarget, GLuint texture, GLint level); +extern GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer, + GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + + #if defined(WIN32) // WGL_ARB_create_context diff --git a/src/renderergl2/tr_dsa.c b/src/renderergl2/tr_dsa.c index 9472bb40..aeb39d78 100644 --- a/src/renderergl2/tr_dsa.c +++ b/src/renderergl2/tr_dsa.c @@ -28,6 +28,10 @@ static struct GLenum texunit; GLuint program; + + GLuint drawFramebuffer; + GLuint readFramebuffer; + GLuint renderbuffer; } glDsaState; @@ -197,3 +201,84 @@ GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location, GL_UseProgramObject(program); qglUniformMatrix4fvARB(location, count, transpose, value); } + +void GL_BindNullFramebuffers() +{ + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0; + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glDsaState.readFramebuffer = 0; +} + +void GL_BindFramebuffer(GLenum target, GLuint framebuffer) +{ + switch (target) + { + case GL_FRAMEBUFFER_EXT: + if (framebuffer != glDsaState.drawFramebuffer || framebuffer != glDsaState.readFramebuffer) + { + qglBindFramebufferEXT(target, framebuffer); + glDsaState.drawFramebuffer = glDsaState.readFramebuffer = framebuffer; + } + break; + + case GL_DRAW_FRAMEBUFFER_EXT: + if (framebuffer != glDsaState.drawFramebuffer) + { + qglBindFramebufferEXT(target, framebuffer); + glDsaState.drawFramebuffer = framebuffer; + } + break; + + case GL_READ_FRAMEBUFFER_EXT: + if (framebuffer != glDsaState.readFramebuffer) + { + qglBindFramebufferEXT(target, framebuffer); + glDsaState.readFramebuffer = framebuffer; + } + break; + } +} + +void GL_BindRenderbuffer(GLuint renderbuffer) +{ + if (renderbuffer != glDsaState.renderbuffer) + { + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, renderbuffer); + glDsaState.renderbuffer = renderbuffer; + } +} + +GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer, + GLenum internalformat, GLsizei width, GLsizei height) +{ + GL_BindRenderbuffer(renderbuffer); + qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalformat, width, height); +} + +GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer, + GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + GL_BindRenderbuffer(renderbuffer); + qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, internalformat, width, height); +} + +GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target) +{ + GL_BindFramebuffer(target, framebuffer); + return qglCheckFramebufferStatusEXT(target); +} + +GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer, + GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer); + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, textarget, texture, level); +} + +GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer, + GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, framebuffer); + qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, renderbuffertarget, renderbuffer); +} diff --git a/src/renderergl2/tr_dsa.h b/src/renderergl2/tr_dsa.h index 164ab065..e820fe00 100644 --- a/src/renderergl2/tr_dsa.h +++ b/src/renderergl2/tr_dsa.h @@ -60,4 +60,21 @@ GLvoid APIENTRY GLDSA_ProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +void GL_BindNullFramebuffers(void); +void GL_BindFramebuffer(GLenum target, GLuint framebuffer); +void GL_BindRenderbuffer(GLuint renderbuffer); + +GLvoid APIENTRY GLDSA_NamedRenderbufferStorage(GLuint renderbuffer, + GLenum internalformat, GLsizei width, GLsizei height); + +GLvoid APIENTRY GLDSA_NamedRenderbufferStorageMultisample(GLuint renderbuffer, + GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +GLenum APIENTRY GLDSA_CheckNamedFramebufferStatus(GLuint framebuffer, GLenum target); +GLvoid APIENTRY GLDSA_NamedFramebufferTexture2D(GLuint framebuffer, + GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLvoid APIENTRY GLDSA_NamedFramebufferRenderbuffer(GLuint framebuffer, + GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + #endif diff --git a/src/renderergl2/tr_extensions.c b/src/renderergl2/tr_extensions.c index bb668da2..2972aaef 100644 --- a/src/renderergl2/tr_extensions.c +++ b/src/renderergl2/tr_extensions.c @@ -216,6 +216,19 @@ GLvoid(APIENTRY * qglProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLvoid(APIENTRY * qglNamedRenderbufferStorage)(GLuint renderbuffer, + GLenum internalformat, GLsizei width, GLsizei height); + +GLvoid(APIENTRY * qglNamedRenderbufferStorageMultisample)(GLuint renderbuffer, + GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + +GLenum(APIENTRY * qglCheckNamedFramebufferStatus)(GLuint framebuffer, GLenum target); +GLvoid(APIENTRY * qglNamedFramebufferTexture2D)(GLuint framebuffer, + GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLvoid(APIENTRY * qglNamedFramebufferRenderbuffer)(GLuint framebuffer, + GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + + static qboolean GLimp_HaveExtension(const char *ext) { const char *ptr = Q_stristr( glConfig.extensions_string, ext ); @@ -803,6 +816,12 @@ void GLimp_InitExtraExtensions() qglProgramUniform1fv = GLDSA_ProgramUniform1fv; qglProgramUniformMatrix4fv = GLDSA_ProgramUniformMatrix4fv; + qglNamedRenderbufferStorage = GLDSA_NamedRenderbufferStorage; + qglNamedRenderbufferStorageMultisample = GLDSA_NamedRenderbufferStorageMultisample; + qglCheckNamedFramebufferStatus = GLDSA_CheckNamedFramebufferStatus; + qglNamedFramebufferTexture2D = GLDSA_NamedFramebufferTexture2D; + qglNamedFramebufferRenderbuffer = GLDSA_NamedFramebufferRenderbuffer; + glRefConfig.directStateAccess = qfalse; if (GLimp_HaveExtension(extension)) { @@ -826,6 +845,12 @@ void GLimp_InitExtraExtensions() qglProgramUniform4f = (void *)SDL_GL_GetProcAddress("glProgramUniform4fEXT"); qglProgramUniform1fv = (void *)SDL_GL_GetProcAddress("glProgramUniform1fvEXT"); qglProgramUniformMatrix4fv = (void *)SDL_GL_GetProcAddress("glProgramUniformMatrix4fvEXT"); + + qglNamedRenderbufferStorage = (void *)SDL_GL_GetProcAddress("glNamedRenderbufferStorageEXT"); + qglNamedRenderbufferStorageMultisample = (void *)SDL_GL_GetProcAddress("glNamedRenderbufferStorageMultisampleEXT"); + qglCheckNamedFramebufferStatus = (void *)SDL_GL_GetProcAddress("glCheckNamedFramebufferStatusEXT"); + qglNamedFramebufferTexture2D = (void *)SDL_GL_GetProcAddress("glNamedFramebufferTexture2DEXT"); + qglNamedFramebufferRenderbuffer = (void *)SDL_GL_GetProcAddress("glNamedFramebufferRenderbufferEXT"); } ri.Printf(PRINT_ALL, result[glRefConfig.directStateAccess ? 1 : 0], extension); diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index c8ea0aeb..6ee533f3 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_fbo.c #include "tr_local.h" +#include "tr_dsa.h" + /* ============= R_CheckFBO @@ -30,19 +32,10 @@ R_CheckFBO */ qboolean R_CheckFBO(const FBO_t * fbo) { - int code; - int id; - - qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &id); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer); - - code = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + GLenum code = qglCheckNamedFramebufferStatus(fbo->frameBuffer, GL_FRAMEBUFFER_EXT); if(code == GL_FRAMEBUFFER_COMPLETE_EXT) - { - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); return qtrue; - } // an error occured switch (code) @@ -83,13 +76,9 @@ qboolean R_CheckFBO(const FBO_t * fbo) default: ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) unknown error 0x%X\n", fbo->name, code); - //ri.Error(ERR_FATAL, "R_CheckFBO: (%s) unknown error 0x%X", fbo->name, code); - //assert(0); break; } - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - return qfalse; } @@ -133,6 +122,11 @@ FBO_t *FBO_Create(const char *name, int width, int height) return fbo; } +/* +================= +FBO_CreateBuffer +================= +*/ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample) { uint32_t *pRenderBuffer; @@ -189,115 +183,45 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample) if (absent) qglGenRenderbuffersEXT(1, pRenderBuffer); - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, *pRenderBuffer); if (multisample && glRefConfig.framebufferMultisample) - { - qglRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, multisample, format, fbo->width, fbo->height); - } + qglNamedRenderbufferStorageMultisample(*pRenderBuffer, multisample, format, fbo->width, fbo->height); else - { - qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, format, fbo->width, fbo->height); - } + qglNamedRenderbufferStorage(*pRenderBuffer, format, fbo->width, fbo->height); if(absent) { if (attachment == 0) { - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); + qglNamedFramebufferRenderbuffer(fbo->frameBuffer, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); + qglNamedFramebufferRenderbuffer(fbo->frameBuffer, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, *pRenderBuffer); } else - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer); + { + qglNamedFramebufferRenderbuffer(fbo->frameBuffer, attachment, GL_RENDERBUFFER_EXT, *pRenderBuffer); + } } } /* ================= -R_AttachFBOTexture1D +FBO_AttachImage ================= */ -void R_AttachFBOTexture1D(int texId, int index) +void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment) { - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture1D: invalid attachment index %i\n", index); - return; - } + GLenum target = GL_TEXTURE_2D; + int index; - qglFramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_1D, texId, 0); -} + if (image->flags & IMGFLAG_CUBEMAP) + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; -/* -================= -R_AttachFBOTexture2D -================= -*/ -void R_AttachFBOTexture2D(int target, int texId, int index) -{ - if(target != GL_TEXTURE_2D && (target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB || target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid target %i\n", target); - return; - } - - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture2D: invalid attachment index %i\n", index); - return; - } - - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, target, texId, 0); -} - -/* -================= -R_AttachFBOTexture3D -================= -*/ -void R_AttachFBOTexture3D(int texId, int index, int zOffset) -{ - if(index < 0 || index >= glRefConfig.maxColorAttachments) - { - ri.Printf(PRINT_WARNING, "R_AttachFBOTexture3D: invalid attachment index %i\n", index); - return; - } - - qglFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + index, GL_TEXTURE_3D_EXT, texId, 0, zOffset); -} - -/* -================= -R_AttachFBOTextureDepth -================= -*/ -void R_AttachFBOTextureDepth(int texId) -{ - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); + qglNamedFramebufferTexture2D(fbo->frameBuffer, attachment, target, image->texnum, 0); + index = attachment - GL_COLOR_ATTACHMENT0_EXT; + if (index >= 0 && index <= 15) + fbo->colorImage[index] = image; } -/* -================= -R_AttachFBOTexturePackedDepthStencil -================= -*/ -void R_AttachFBOTexturePackedDepthStencil(int texId) -{ - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, texId, 0); -} - -void FBO_AttachTextureImage(image_t *img, int index) -{ - if (!glState.currentFBO) - { - ri.Printf(PRINT_WARNING, "FBO: attempted to attach a texture image with no FBO bound!\n"); - return; - } - - R_AttachFBOTexture2D(GL_TEXTURE_2D, img->texnum, index); - glState.currentFBO->colorImage[index] = img; -} /* ============ @@ -312,38 +236,10 @@ void FBO_Bind(FBO_t * fbo) if (r_logFile->integer) { // don't just call LogComment, or we will get a call to va() every frame! - if (fbo) - GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo->name)); - else - GLimp_LogComment("--- FBO_Bind ( NULL ) ---\n"); - } - - if (!fbo) - { - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - glState.currentFBO = NULL; - - return; + GLimp_LogComment(va("--- FBO_Bind( %s ) ---\n", fbo ? fbo->name : "NULL")); } - - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->frameBuffer); - - /* - if(fbo->colorBuffers[0]) - { - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->colorBuffers[0]); - } - */ - - /* - if(fbo->depthBuffer) - { - qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo->depthBuffer); - qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbo->depthBuffer); - } - */ + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, fbo ? fbo->frameBuffer : 0); glState.currentFBO = fbo; } @@ -355,7 +251,6 @@ FBO_Init void FBO_Init(void) { int i; - // int width, height, hdrFormat, multisample; int hdrFormat, multisample; ri.Printf(PRINT_ALL, "------- FBO_Init -------\n"); @@ -369,73 +264,40 @@ void FBO_Init(void) R_IssuePendingRenderCommands(); -/* if(glRefConfig.textureNonPowerOfTwo) - { - width = glConfig.vidWidth; - height = glConfig.vidHeight; - } - else - { - width = NextPowerOfTwo(glConfig.vidWidth); - height = NextPowerOfTwo(glConfig.vidHeight); - } */ - hdrFormat = GL_RGBA8; if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat) - { hdrFormat = GL_RGBA16F_ARB; - } qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample); if (r_ext_framebuffer_multisample->integer < multisample) - { multisample = r_ext_framebuffer_multisample->integer; - } if (multisample < 2 || !glRefConfig.framebufferBlit) multisample = 0; if (multisample != r_ext_framebuffer_multisample->integer) - { ri.Cvar_SetValue("r_ext_framebuffer_multisample", (float)multisample); - } // only create a render FBO if we need to resolve MSAA or do HDR // otherwise just render straight to the screen (tr.renderFbo = NULL) if (multisample && glRefConfig.framebufferMultisample) { tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.renderFbo); - FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, multisample); FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, multisample); - R_CheckFBO(tr.renderFbo); - tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.msaaResolveFbo); - - //FBO_CreateBuffer(tr.msaaResolveFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.renderImage, 0); - - //FBO_CreateBuffer(tr.msaaResolveFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - + FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); R_CheckFBO(tr.msaaResolveFbo); } else if (r_hdr->integer) { tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.renderFbo); - - //FBO_CreateBuffer(tr.renderFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.renderImage, 0); - - //FBO_CreateBuffer(tr.renderFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - + FBO_AttachImage(tr.renderFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); R_CheckFBO(tr.renderFbo); } @@ -443,20 +305,15 @@ void FBO_Init(void) // this fixes the corrupt screen bug with r_hdr 1 on older hardware if (tr.renderFbo) { - FBO_Bind(tr.renderFbo); + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, tr.renderFbo->frameBuffer); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - FBO_Bind(NULL); } if (r_drawSunRays->integer) { tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_Bind(tr.sunRaysFbo); - - FBO_AttachTextureImage(tr.sunRaysImage, 0); - - R_AttachFBOTextureDepth(tr.renderDepthImage->texnum); - + FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); R_CheckFBO(tr.sunRaysFbo); } @@ -466,14 +323,8 @@ void FBO_Init(void) for( i = 0; i < MAX_DRAWN_PSHADOWS; i++) { tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height); - FBO_Bind(tr.pshadowFbos[i]); - - //FBO_CreateBuffer(tr.pshadowFbos[i], GL_RGBA8, 0, 0); - FBO_AttachTextureImage(tr.pshadowMaps[i], 0); - + FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], GL_COLOR_ATTACHMENT0_EXT); FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0); - //R_AttachFBOTextureDepth(tr.textureDepthImage->texnum); - R_CheckFBO(tr.pshadowFbos[i]); } } @@ -483,104 +334,64 @@ void FBO_Init(void) for ( i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); - FBO_Bind(tr.sunShadowFbo[i]); - - //FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0); - //FBO_AttachTextureImage(tr.sunShadowImage, 0); - qglDrawBuffer(GL_NONE); - qglReadBuffer(GL_NONE); - - //FBO_CreateBuffer(tr.sunShadowFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_AttachFBOTextureDepth(tr.sunShadowDepthImage[i]->texnum); - + FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT); R_CheckFBO(tr.sunShadowFbo[i]); - } tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height); - FBO_Bind(tr.screenShadowFbo); - - FBO_AttachTextureImage(tr.screenShadowImage, 0); - + FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.screenShadowFbo); } for (i = 0; i < 2; i++) { tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); - FBO_Bind(tr.textureScratchFbo[i]); - - //FBO_CreateBuffer(tr.textureScratchFbo[i], GL_RGBA8, 0, 0); - FBO_AttachTextureImage(tr.textureScratchImage[i], 0); - + FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.textureScratchFbo[i]); } { tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height); - FBO_Bind(tr.calcLevelsFbo); - - //FBO_CreateBuffer(tr.calcLevelsFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.calcLevelsImage, 0); - + FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.calcLevelsFbo); } { tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height); - FBO_Bind(tr.targetLevelsFbo); - - //FBO_CreateBuffer(tr.targetLevelsFbo, hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.targetLevelsImage, 0); - + FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.targetLevelsFbo); } for (i = 0; i < 2; i++) { tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); - FBO_Bind(tr.quarterFbo[i]); - - //FBO_CreateBuffer(tr.quarterFbo[i], hdrFormat, 0, 0); - FBO_AttachTextureImage(tr.quarterImage[i], 0); - + FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.quarterFbo[i]); } if (r_ssao->integer) { tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height); - FBO_Bind(tr.hdrDepthFbo); - - FBO_AttachTextureImage(tr.hdrDepthImage, 0); - + FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.hdrDepthFbo); tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height); - FBO_Bind(tr.screenSsaoFbo); - - FBO_AttachTextureImage(tr.screenSsaoImage, 0); - + FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0_EXT); R_CheckFBO(tr.screenSsaoFbo); } if (tr.renderCubeImage) { tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height); - FBO_Bind(tr.renderCubeFbo); - - //FBO_AttachTextureImage(tr.renderCubeImage, 0); - R_AttachFBOTexture2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, tr.renderCubeImage->texnum, 0); - glState.currentFBO->colorImage[0] = tr.renderCubeImage; - + FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, GL_COLOR_ATTACHMENT0_EXT); FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); - R_CheckFBO(tr.renderCubeFbo); } GL_CheckErrors(); - FBO_Bind(NULL); + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0); + glState.currentFBO = NULL; } /* @@ -849,12 +660,12 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu VectorSet4(dstBoxFinal, dstBox[0], dstBox[1], dstBox[0] + dstBox[2], dstBox[1] + dstBox[3]); } - qglBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, srcFb); - qglBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dstFb); + GL_BindFramebuffer(GL_READ_FRAMEBUFFER_EXT, srcFb); + GL_BindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, dstFb); qglBlitFramebufferEXT(srcBoxFinal[0], srcBoxFinal[1], srcBoxFinal[2], srcBoxFinal[3], dstBoxFinal[0], dstBoxFinal[1], dstBoxFinal[2], dstBoxFinal[3], buffers, filter); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + GL_BindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glState.currentFBO = NULL; } diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 8e27c620..0c02f887 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -887,6 +887,7 @@ void GL_SetDefaultState( void ) qglColor4f (1,1,1,1); GL_BindNullTextures(); + GL_BindNullFramebuffers(); qglEnable(GL_TEXTURE_2D); GL_TextureMode( r_textureMode->string ); -- cgit From 8032873df3b9f0ca2498cf79c3874a50406cc427 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 21 Jan 2016 22:31:41 -0800 Subject: OpenGL2: Some FBO related cleanup/fixes. --- src/renderergl2/tr_backend.c | 52 +++++-------------- src/renderergl2/tr_fbo.c | 39 ++++++++------- src/renderergl2/tr_fbo.h | 1 + src/renderergl2/tr_postprocess.c | 105 ++++++++++++++++----------------------- 4 files changed, 77 insertions(+), 120 deletions(-) diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index e6dd3cfa..ae475b02 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ #include "tr_local.h" +#include "tr_fbo.h" #include "tr_dsa.h" backEndData_t *backEndData; @@ -378,31 +379,20 @@ void RB_BeginDrawingView (void) { if (glRefConfig.framebufferObject) { + FBO_t *fbo = backEnd.viewParms.targetFbo; + // FIXME: HUGE HACK: render to the screen fbo if we've already postprocessed the frame and aren't drawing more world // drawing more world check is in case of double renders, such as skyportals - if (backEnd.viewParms.targetFbo == NULL) + if (fbo == NULL && !(backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) + fbo = tr.renderFbo; + + if (tr.renderCubeFbo && fbo == tr.renderCubeFbo) { - if (!tr.renderFbo || (backEnd.framePostProcessed && (backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } + cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; + FBO_AttachImage(fbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, backEnd.viewParms.targetFboLayer); } - else - { - FBO_Bind(backEnd.viewParms.targetFbo); - // FIXME: hack for cubemap testing - if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) - { - cubemap_t *cubemap = &tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex]; - //qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, backEnd.viewParms.targetFbo->colorImage[0]->texnum, 0); - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + backEnd.viewParms.targetFboLayer, cubemap->image->texnum, 0); - } - } + FBO_Bind(fbo); } // @@ -781,14 +771,7 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte * // FIXME: HUGE hack if (glRefConfig.framebufferObject) { - if (!tr.renderFbo || backEnd.framePostProcessed) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } + FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); } RB_SetGL2D(); @@ -874,16 +857,7 @@ const void *RB_StretchPic ( const void *data ) { // FIXME: HUGE hack if (glRefConfig.framebufferObject) - { - if (!tr.renderFbo || backEnd.framePostProcessed) - { - FBO_Bind(NULL); - } - else - { - FBO_Bind(tr.renderFbo); - } - } + FBO_Bind(backEnd.framePostProcessed ? NULL : tr.renderFbo); RB_SetGL2D(); @@ -1696,7 +1670,7 @@ const void *RB_ExportCubemaps(const void *data) for (j = 0; j < 6; j++) { - qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0); + FBO_AttachImage(tr.renderCubeFbo, cubemap->image, GL_COLOR_ATTACHMENT0_EXT, j); qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p); p += sideSize; } diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index 6ee533f3..59b17032 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -208,13 +208,13 @@ void FBO_CreateBuffer(FBO_t *fbo, int format, int index, int multisample) FBO_AttachImage ================= */ -void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment) +void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside) { GLenum target = GL_TEXTURE_2D; int index; if (image->flags & IMGFLAG_CUBEMAP) - target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; + target = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB + cubemapside; qglNamedFramebufferTexture2D(fbo->frameBuffer, attachment, target, image->texnum, 0); index = attachment - GL_COLOR_ATTACHMENT0_EXT; @@ -289,15 +289,15 @@ void FBO_Init(void) R_CheckFBO(tr.renderFbo); tr.msaaResolveFbo = FBO_Create("_msaaResolve", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT); - FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); + FBO_AttachImage(tr.msaaResolveFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT, 0); + FBO_AttachImage(tr.msaaResolveFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.msaaResolveFbo); } else if (r_hdr->integer) { tr.renderFbo = FBO_Create("_render", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_AttachImage(tr.renderFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT); - FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); + FBO_AttachImage(tr.renderFbo, tr.renderImage, GL_COLOR_ATTACHMENT0_EXT, 0); + FBO_AttachImage(tr.renderFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.renderFbo); } @@ -312,8 +312,8 @@ void FBO_Init(void) if (r_drawSunRays->integer) { tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height); - FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0_EXT); - FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT); + FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0_EXT, 0); + FBO_AttachImage(tr.sunRaysFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.sunRaysFbo); } @@ -323,7 +323,7 @@ void FBO_Init(void) for( i = 0; i < MAX_DRAWN_PSHADOWS; i++) { tr.pshadowFbos[i] = FBO_Create(va("_shadowmap%d", i), tr.pshadowMaps[i]->width, tr.pshadowMaps[i]->height); - FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.pshadowFbos[i], tr.pshadowMaps[i], GL_COLOR_ATTACHMENT0_EXT, 0); FBO_CreateBuffer(tr.pshadowFbos[i], GL_DEPTH_COMPONENT24_ARB, 0, 0); R_CheckFBO(tr.pshadowFbos[i]); } @@ -334,56 +334,56 @@ void FBO_Init(void) for ( i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); - FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT); + FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.sunShadowFbo[i]); } tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height); - FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.screenShadowFbo); } for (i = 0; i < 2; i++) { tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); - FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.textureScratchFbo[i]); } { tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height); - FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.calcLevelsFbo); } { tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height); - FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.targetLevelsFbo); } for (i = 0; i < 2; i++) { tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); - FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.quarterFbo[i]); } if (r_ssao->integer) { tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height); - FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.hdrDepthFbo); tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height); - FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.screenSsaoFbo); } if (tr.renderCubeImage) { tr.renderCubeFbo = FBO_Create("_renderCubeFbo", tr.renderCubeImage->width, tr.renderCubeImage->height); - FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, GL_COLOR_ATTACHMENT0_EXT); + FBO_AttachImage(tr.renderCubeFbo, tr.renderCubeImage, GL_COLOR_ATTACHMENT0_EXT, 0); FBO_CreateBuffer(tr.renderCubeFbo, GL_DEPTH_COMPONENT24_ARB, 0, 0); R_CheckFBO(tr.renderCubeFbo); } @@ -474,7 +474,10 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS int width, height; if (!src) + { + ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n"); return; + } if (inSrcBox) { diff --git a/src/renderergl2/tr_fbo.h b/src/renderergl2/tr_fbo.h index 530fee5c..72b2c911 100644 --- a/src/renderergl2/tr_fbo.h +++ b/src/renderergl2/tr_fbo.h @@ -52,6 +52,7 @@ typedef struct FBO_s int height; } FBO_t; +void FBO_AttachImage(FBO_t *fbo, image_t *image, GLenum attachment, GLuint cubemapside); void FBO_Bind(FBO_t *fbo); void FBO_Init(void); void FBO_Shutdown(void); diff --git a/src/renderergl2/tr_postprocess.c b/src/renderergl2/tr_postprocess.c index 35982fce..1952ae96 100644 --- a/src/renderergl2/tr_postprocess.c +++ b/src/renderergl2/tr_postprocess.c @@ -183,7 +183,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float FBO_Blit(tr.textureScratchFbo[0], NULL, blurTexScale, tr.textureScratchFbo[1], NULL, &tr.bokehShader, color, 0); } - FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0); + FBO_Blit(tr.textureScratchFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0); } #else // higher quality blur, but slower else if (blur > 1.0f) @@ -217,7 +217,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float FBO_Blit(tr.quarterFbo[0], NULL, blurTexScale, tr.quarterFbo[1], NULL, &tr.bokehShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } - FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, &tr.textureColorShader, NULL, 0); + FBO_Blit(tr.quarterFbo[1], NULL, NULL, dst, dstBox, NULL, NULL, 0); } #endif } @@ -232,49 +232,44 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretc const float mul = powf(stretch, inc); float scale; - { - vec2_t texScale; + alpha *= inc; + VectorSet4(color, alpha, alpha, alpha, 1.0f); - texScale[0] = - texScale[1] = 1.0f; + if (srcFbo) + VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); + else + VectorSet4(srcBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight); - alpha *= inc; - VectorSet4(color, alpha, alpha, alpha, 1.0f); + VectorSet4(dstBox, x, y, w, h); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0); - VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); - VectorSet4(dstBox, x, y, w, h); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0); + --passes; + scale = mul; + while (passes > 0) + { + float iscale = 1.f / scale; + float s0 = xcenter * (1.f - iscale); + float t0 = (1.0f - ycenter) * (1.f - iscale); - --passes; - scale = mul; - while (passes > 0) + if (srcFbo) { - float iscale = 1.f / scale; - float s0 = xcenter * (1.f - iscale); - float t0 = (1.0f - ycenter) * (1.f - iscale); - float s1 = iscale + s0; - float t1 = iscale + t0; - - if (srcFbo) - { - srcBox[0] = s0 * srcFbo->width; - srcBox[1] = t0 * srcFbo->height; - srcBox[2] = (s1 - s0) * srcFbo->width; - srcBox[3] = (t1 - t0) * srcFbo->height; - } - else - { - srcBox[0] = s0 * glConfig.vidWidth; - srcBox[1] = t0 * glConfig.vidHeight; - srcBox[2] = (s1 - s0) * glConfig.vidWidth; - srcBox[3] = (t1 - t0) * glConfig.vidHeight; - } + srcBox[0] = s0 * srcFbo->width; + srcBox[1] = t0 * srcFbo->height; + srcBox[2] = iscale * srcFbo->width; + srcBox[3] = iscale * srcFbo->height; + } + else + { + srcBox[0] = s0 * glConfig.vidWidth; + srcBox[1] = t0 * glConfig.vidHeight; + srcBox[2] = iscale * glConfig.vidWidth; + srcBox[3] = iscale * glConfig.vidHeight; + } - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - scale *= mul; - --passes; - } + scale *= mul; + --passes; } } @@ -329,7 +324,7 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox) // From RB_DrawSun() { float dist; - mat4_t trans, model, mvp; + mat4_t trans, model; Mat4Translation( backEnd.viewParms.or.origin, trans ); Mat4Multiply( backEnd.viewParms.world.modelMatrix, trans, model ); @@ -353,12 +348,8 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox) // initialize quarter buffers { float mul = 1.f; - vec2_t texScale; ivec4_t rayBox, quarterBox; - texScale[0] = - texScale[1] = 1.0f; - VectorSet4(color, mul, mul, mul, 1); if (srcFbo) @@ -408,14 +399,10 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox) // add result back on top of the main buffer { float mul = 1.f; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; VectorSet4(color, mul, mul, mul, 1); - FBO_Blit(tr.quarterFbo[0], NULL, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); + FBO_Blit(tr.quarterFbo[0], NULL, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); } } @@ -443,31 +430,27 @@ static void RB_BlurAxis(FBO_t *srcFbo, FBO_t *dstFbo, float strength, qboolean h { ivec4_t srcBox, dstBox; vec4_t color; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; VectorSet4(color, weights[0], weights[0], weights[0], 1.0f); VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); VectorSet4(dstBox, 0, 0, dstFbo->width, dstFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, 0 ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0); VectorSet4(color, weights[1], weights[1], weights[1], 1.0f); dx = offsets[1] * xmul; dy = offsets[1] * ymul; VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); VectorSet4(color, weights[2], weights[2], weights[2], 1.0f); dx = offsets[2] * xmul; dy = offsets[2] * ymul; VectorSet4(srcBox, dx, dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); VectorSet4(srcBox, -dx, -dy, srcFbo->width, srcFbo->height); - FBO_Blit(srcFbo, srcBox, texScale, dstFbo, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); + FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); } } @@ -492,10 +475,6 @@ void RB_GaussianBlur(float blur) { ivec4_t srcBox, dstBox; vec4_t color; - vec2_t texScale; - - texScale[0] = - texScale[1] = 1.0f; VectorSet4(color, 1, 1, 1, 1); @@ -507,7 +486,7 @@ void RB_GaussianBlur(float blur) VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height); VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - FBO_BlitFromTexture(tr.whiteImage, srcBox, texScale, tr.textureScratchFbo[0], dstBox, &tr.textureColorShader, color, GLS_DEPTHTEST_DISABLE); + FBO_BlitFromTexture(tr.whiteImage, srcBox, NULL, tr.textureScratchFbo[0], dstBox, NULL, color, GLS_DEPTHTEST_DISABLE); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // blur the tiny buffer horizontally and vertically @@ -518,6 +497,6 @@ void RB_GaussianBlur(float blur) VectorSet4(srcBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); VectorSet4(dstBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight); color[3] = factor; - FBO_Blit(tr.textureScratchFbo[0], srcBox, texScale, NULL, dstBox, &tr.textureColorShader, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); + FBO_Blit(tr.textureScratchFbo[0], srcBox, NULL, NULL, dstBox, NULL, color, GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } } -- cgit From 9f1aa0dfc09915681d66d16c6bce7768a280a08a Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 28 Jan 2016 16:39:42 -0800 Subject: OpenGL2: Load existing per-map cubemaps. --- src/renderergl2/tr_bsp.c | 39 ++++-- src/renderergl2/tr_dsa.c | 3 + src/renderergl2/tr_image.c | 317 +++++++++++++++++++++++---------------------- 3 files changed, 196 insertions(+), 163 deletions(-) diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index e0a97d4d..7e5493f3 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -3069,23 +3069,41 @@ void R_AssignCubemapsToWorldSurfaces(void) } -void R_RenderAllCubemaps(void) +void R_LoadCubemaps(void) { - int i, j; + int i; + imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP; for (i = 0; i < tr.numCubemaps; i++) { - tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); + char filename[MAX_QPATH]; + cubemap_t *cubemap = &tr.cubemaps[i]; + + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); + + cubemap->image = R_FindImageFile(filename, IMGTYPE_COLORALPHA, flags); } +} + + +void R_RenderMissingCubemaps(void) +{ + int i, j; + imgFlags_t flags = IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP; for (i = 0; i < tr.numCubemaps; i++) { - for (j = 0; j < 6; j++) + if (!tr.cubemaps[i].image) { - RE_ClearScene(); - R_RenderCubemapSide(i, j, qfalse); - R_IssuePendingRenderCommands(); - R_InitNextFrame(); + tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, flags, GL_RGBA8); + + for (j = 0; j < 6; j++) + { + RE_ClearScene(); + R_RenderCubemapSide(i, j, qfalse); + R_IssuePendingRenderCommands(); + R_InitNextFrame(); + } } } } @@ -3426,10 +3444,11 @@ void RE_LoadWorldMap( const char *name ) { // make sure the VAO glState entry is safe R_BindNullVao(); - // Render all cubemaps + // Render or load all cubemaps if (r_cubeMapping->integer && tr.numCubemaps) { - R_RenderAllCubemaps(); + R_LoadCubemaps(); + R_RenderMissingCubemaps(); } ri.FS_FreeFile( buffer.v ); diff --git a/src/renderergl2/tr_dsa.c b/src/renderergl2/tr_dsa.c index aeb39d78..a766263a 100644 --- a/src/renderergl2/tr_dsa.c +++ b/src/renderergl2/tr_dsa.c @@ -68,6 +68,9 @@ int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture) if (glDsaState.textures[tmu] == texture) return 0; + if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) + target = GL_TEXTURE_CUBE_MAP; + qglBindMultiTexture(texunit, target, texture); glDsaState.textures[tmu] = texture; return 1; diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index aade799e..88335b7a 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -1864,82 +1864,57 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width, ri.Hunk_FreeTempMemory(compressedData); } - -static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) +static int CalculateMipSize(int width, int height, GLenum picFormat) { - int dataFormat, dataType; - qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); + int numBlocks = ((width + 3) / 4) * ((height + 3) / 4); + int numPixels = width * height; - if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) + switch (picFormat) { - int bytesPer4x4Block = 0; - int miplevel = 0; - - switch (picFormat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RED_RGTC1: - case GL_COMPRESSED_SIGNED_RED_RGTC1: - bytesPer4x4Block = 8; - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: - case GL_COMPRESSED_RG_RGTC2: - case GL_COMPRESSED_SIGNED_RG_RGTC2: - case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: - case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: - case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: - case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: - bytesPer4x4Block = 16; - break; - default: - ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat); - return; - break; - } - - if (flags & IMGFLAG_PICMIP) - { - for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--) - { - int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RED_RGTC1: + case GL_COMPRESSED_SIGNED_RED_RGTC1: + return numBlocks * 8; + + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + case GL_COMPRESSED_RG_RGTC2: + case GL_COMPRESSED_SIGNED_RG_RGTC2: + case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: + case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: + case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: + case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: + return numBlocks * 16; + + case GL_RGBA8: + case GL_SRGB8_ALPHA8_EXT: + return numPixels * 4; - x >>= 1; - y >>= 1; - width = MAX(1, width >> 1); - height = MAX(1, height >> 1); - data += size; - } - } - - if (!(flags & IMGFLAG_MIPMAP)) - numMips = 1; - - for (miplevel = 0; miplevel < numMips; miplevel++) - { - int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block; + default: + ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat); + return 0; + } - if (subtexture) - qglCompressedTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data); - else - qglCompressedTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, size, data); + return 0; +} - x >>= 1; - y >>= 1; - width = MAX(1, width >> 1); - height = MAX(1, height >> 1); - data += size; - } - return; - } +static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture ) +{ + int dataFormat, dataType; + qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); + qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT)); + qboolean mipmap = !!(flags & IMGFLAG_MIPMAP); + qboolean picmip = !!(flags & IMGFLAG_PICMIP); + int size, miplevel; + qboolean lastMip = qfalse; - switch(internalFormat) + switch (internalFormat) { case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16_ARB: @@ -1958,52 +1933,83 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int break; } - if ( subtexture ) - qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data ); - else + if (!data) { - if (rgtc) - RawImage_UploadToRgtc2Texture(texture, data, width, height, 0); - else - qglTextureImage2D(texture, GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data); + miplevel = 0; + do + { + lastMip = (width == 1 && height == 1) || !mipmap; + qglTextureImage2D(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, NULL); + + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + miplevel++; + } + while (!lastMip); + + return; } - if (flags & IMGFLAG_MIPMAP) + if (compressed && picmip) { - int miplevel = 0; - - while (width > 1 || height > 1) + for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--) { - if (data) - { - if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) - R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap ); - else - R_MipMapsRGB( data, width, height ); - } - + size = CalculateMipSize(width, height, picFormat); + x >>= 1; + y >>= 1; width = MAX(1, width >> 1); height = MAX(1, height >> 1); - miplevel++; + data += size; + } + } - if ( data && r_colorMipLevels->integer ) - R_BlendOverTexture( (byte *)data, width * height, mipBlendColors[miplevel] ); + miplevel = 0; + do + { + lastMip = (width == 1 && height == 1) || !mipmap; + size = CalculateMipSize(width, height, picFormat); - if ( subtexture ) - { - x >>= 1; - y >>= 1; - qglTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data ); - } + if (compressed) + { + if (subtexture) + qglCompressedTextureSubImage2D(texture, target, miplevel, x, y, width, height, picFormat, size, data); + else + qglCompressedTextureImage2D(texture, target, miplevel, picFormat, width, height, 0, size, data); + } + else + { + if (miplevel != 0 && r_colorMipLevels->integer) + R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]); + + if (rgtc) + RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel); + else if (subtexture) + qglTextureSubImage2D(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data); else + qglTextureImage2D(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); + + if (!lastMip && numMips < 2) { - if (rgtc) - RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel); + if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT) + R_MipMapNormalHeight(data, data, width, height, glRefConfig.swizzleNormalmap); else - qglTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); + R_MipMapsRGB(data, width, height); } } + + x >>= 1; + y >>= 1; + width = MAX(1, width >> 1); + height = MAX(1, height >> 1); + miplevel++; + + if (numMips > 1) + { + data += size; + numMips--; + } } + while (!lastMip); } @@ -2024,19 +2030,35 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic GLenum internalFormat = image->internalFormat; qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height); qboolean notScaled = qtrue; - qboolean mipmap = !!(flags & IMGFLAG_MIPMAP); + qboolean compressed = (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT); + qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1); + qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP); + GLenum uploadTarget = cubemap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : GL_TEXTURE_2D; + GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D; + int depth = cubemap ? 6 : 1; if (!data) { RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL); - RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); + for (i = 0; i < depth; i++) + RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, uploadTarget + i, GL_RGBA8, 0, internalFormat, type, flags, qfalse); goto done; } else if (!subtexture) { - if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) + if (compressed || cubemap) { - RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); + for (i = 0; i < depth; i++) + { + int w2 = width, h2 = height; + RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget + i, picFormat, numMips, internalFormat, type, flags, qfalse); + for (c = numMips; c; c--) + { + data += CalculateMipSize(w2, h2, picFormat); + w2 = MAX(1, w2 >> 1); + h2 = MAX(1, h2 >> 1); + } + } goto done; } notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer); @@ -2076,12 +2098,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic if (subtexture) { // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped - RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue); + RawImage_UploadTexture(image->texnum, data, x, y, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qtrue); GL_CheckErrors(); return; } - RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); + RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse); done: @@ -2090,20 +2112,20 @@ done: if (mipmap) { - if ( glConfig.textureFilterAnisotropic ) - qglTextureParameteri( image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) ); + if (glConfig.textureFilterAnisotropic && !cubemap) + qglTextureParameteri(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, + (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer)); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max); } else { - if ( glConfig.textureFilterAnisotropic ) - qglTextureParameteri(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); + if (glConfig.textureFilterAnisotropic && !cubemap) + qglTextureParameteri(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } // Fix for sampling depth buffer on old nVidia cards @@ -2114,9 +2136,9 @@ done: case GL_DEPTH_COMPONENT16_ARB: case GL_DEPTH_COMPONENT24_ARB: case GL_DEPTH_COMPONENT32_ARB: - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTextureParameterf(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; default: break; @@ -2170,49 +2192,20 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe glWrapClampMode = GL_REPEAT; if (!internalFormat) - { - if (image->flags & IMGFLAG_CUBEMAP) - internalFormat = GL_RGBA8; - else - internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags); - } + internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags); image->internalFormat = internalFormat; + Upload32(pic, 0, 0, image->width, image->height, picFormat, numMips, image); + if (image->flags & IMGFLAG_CUBEMAP) { - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - if (image->flags & IMGFLAG_MIPMAP) - { - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - } - else - { - qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic); - - if (image->flags & IMGFLAG_MIPMAP) - qglGenerateTextureMipmap(image->texnum, GL_TEXTURE_CUBE_MAP); - - image->uploadWidth = width; - image->uploadHeight = height; + qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glWrapClampMode); + qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glWrapClampMode); + qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glWrapClampMode); } else { - Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image ); - qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode); qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode); } @@ -2384,6 +2377,7 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) GLenum picFormat; int picNumMips; long hash; + imgFlags_t checkFlagsTrue, checkFlagsFalse; if (!name) { return NULL; @@ -2414,7 +2408,10 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) return NULL; } - if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) + checkFlagsTrue = IMGFLAG_PICMIP | IMGFLAG_MIPMAP | IMGFLAG_GENNORMALMAP; + checkFlagsFalse = IMGFLAG_CUBEMAP; + if (r_normalMapping->integer && (picFormat == GL_RGBA8) && (type == IMGTYPE_COLORALPHA) && + ((flags & checkFlagsTrue) == checkFlagsTrue) && !(flags & checkFlagsFalse)) { char normalName[MAX_QPATH]; image_t *normalImage; @@ -2517,6 +2514,20 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags ) } } + // force mipmaps off if image is compressed but doesn't have enough mips + if ((flags & IMGFLAG_MIPMAP) && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) + { + int wh = MAX(width, height); + int neededMips = 0; + while (wh) + { + neededMips++; + wh >>= 1; + } + if (neededMips > picNumMips) + flags &= ~IMGFLAG_MIPMAP; + } + image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0 ); ri.Free( pic ); return image; -- cgit From 004db47aa205b6705ae11c86924eb63549127de6 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 29 Jan 2016 20:14:35 -0800 Subject: Fix frame_msec possibly being zero in cl_input.c. This fixes a mouse freezing bug. --- src/client/cl_input.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/client/cl_input.c b/src/client/cl_input.c index 48bf51df..7a917df2 100644 --- a/src/client/cl_input.c +++ b/src/client/cl_input.c @@ -633,6 +633,12 @@ void CL_CreateNewCommands( void ) { frame_msec = com_frameTime - old_com_frameTime; + // if running over 1000fps, act as if each frame is 1ms + // prevents divisions by zero + if ( frame_msec < 1 ) { + frame_msec = 1; + } + // if running less than 5fps, truncate the extra time to prevent // unexpected moves after a hitch if ( frame_msec > 200 ) { -- cgit From d5ba7bb70ef327c8856165475b58e946c8fbd8ce Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 1 Feb 2016 21:37:23 -0800 Subject: OpenGL2: Merge several cvars into r_pbr. r_glossIsRoughness, r_specularIsMetallic, r_framebufferGamma, r_tonemapGamma, r_materialGamma, r_lightGamma --- src/renderergl2/glsl/calclevels4x_fp.glsl | 4 +-- src/renderergl2/glsl/lightall_fp.glsl | 48 ++++++++++--------------- src/renderergl2/glsl/tonemap_fp.glsl | 8 ++--- src/renderergl2/tr_bsp.c | 4 +-- src/renderergl2/tr_glsl.c | 19 ++-------- src/renderergl2/tr_image.c | 5 +++ src/renderergl2/tr_init.c | 18 ++-------- src/renderergl2/tr_local.h | 8 +---- src/renderergl2/tr_scene.c | 2 +- src/renderergl2/tr_shader.c | 60 ++++++++++++++++++++++--------- 10 files changed, 82 insertions(+), 94 deletions(-) diff --git a/src/renderergl2/glsl/calclevels4x_fp.glsl b/src/renderergl2/glsl/calclevels4x_fp.glsl index 1de59e9f..0d298b62 100644 --- a/src/renderergl2/glsl/calclevels4x_fp.glsl +++ b/src/renderergl2/glsl/calclevels4x_fp.glsl @@ -14,8 +14,8 @@ vec3 GetValues(vec2 offset, vec3 current) #ifdef FIRST_PASS - #if defined(r_framebufferGamma) - minAvgMax = pow(minAvgMax, vec3(r_framebufferGamma)); + #if defined(USE_PBR) + minAvgMax = pow(minAvgMax, vec3(2.2)); #endif float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001); diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index b8f3985f..eb8ba900 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -276,9 +276,9 @@ void main() attenuation = 1.0; #endif - #if defined(r_lightGamma) - lightColor = pow(lightColor, vec3(r_lightGamma)); - ambientColor = pow(ambientColor, vec3(r_lightGamma)); + #if defined(USE_PBR) + lightColor = pow(lightColor, vec3(2.2)); + ambientColor = pow(ambientColor, vec3(2.2)); #endif #if defined(USE_NORMALMAP) @@ -319,7 +319,7 @@ void main() // Recover any unused light as ambient, in case attenuation is over 4x or // light is below the surface - ambientColor = clamp(ambientColor - lightColor * surfNL, 0.0, 1.0); + ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0)); #endif vec3 reflectance; @@ -335,21 +335,18 @@ void main() specular *= u_SpecularScale; - #if defined(r_materialGamma) - diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma)); - #if !defined(SPECULAR_IS_METALLIC) - specular.rgb = pow(specular.rgb, vec3(r_materialGamma)); - #endif + #if defined(USE_PBR) + diffuse.rgb = pow(diffuse.rgb, vec3(2.2)); #endif float gloss = specular.a; - #if defined(GLOSS_IS_ROUGHNESS) - float roughness = gloss; + #if defined(USE_PBR) + float roughness = 1.0 - specular.r; #else float roughness = exp2(-3.0 * gloss); #endif - #if defined(SPECULAR_IS_METALLIC) + #if defined(USE_PBR) // diffuse is actually base color, and green of specular is metallicness float metallic = specular.g; @@ -374,7 +371,7 @@ void main() // from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir; - #if defined(GLOSS_IS_ROUGHNESS) + #if defined(USE_PBR) vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 * roughness).rgb * u_EnableTextures.w; #else vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w; @@ -385,8 +382,8 @@ void main() //vec3 cubeLightDiffuse = max(textureCubeLod(u_CubeMap, N, 6.0).rgb, 0.5 / 255.0); //cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721)); - #if defined(r_framebufferGamma) - cubeLightColor = pow(cubeLightColor, vec3(r_framebufferGamma)); + #if defined(USE_PBR) + cubeLightColor = pow(cubeLightColor, vec3(2.2)); #endif // multiply cubemap values by lighting @@ -421,8 +418,8 @@ void main() lightColor = u_PrimaryLightColor; - #if defined(r_lightGamma) - lightColor = pow(lightColor, vec3(r_lightGamma)); + #if defined(USE_PBR) + lightColor = pow(lightColor, vec3(2.2)); #endif #if defined(USE_SHADOWMAP) @@ -434,6 +431,11 @@ void main() gl_FragColor.rgb += lightColor * reflectance * NL2; #endif + + #if defined(USE_PBR) + gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2)); + #endif + #else lightColor = var_Color.rgb; @@ -441,21 +443,9 @@ void main() lightColor *= lightmapColor.rgb; #endif - #if defined(r_lightGamma) - lightColor = pow(lightColor, vec3(r_lightGamma)); - #endif - - #if defined(r_materialGamma) - diffuse.rgb = pow(diffuse.rgb, vec3(r_materialGamma)); - #endif - gl_FragColor.rgb = diffuse.rgb * lightColor; #endif -#if defined(r_framebufferGamma) - gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / r_framebufferGamma)); -#endif - gl_FragColor.a = diffuse.a * var_Color.a; } diff --git a/src/renderergl2/glsl/tonemap_fp.glsl b/src/renderergl2/glsl/tonemap_fp.glsl index 1368c5bd..5d8841d6 100644 --- a/src/renderergl2/glsl/tonemap_fp.glsl +++ b/src/renderergl2/glsl/tonemap_fp.glsl @@ -28,8 +28,8 @@ void main() { vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color; -#if defined(r_framebufferGamma) - color.rgb = pow(color.rgb, vec3(r_framebufferGamma)); +#if defined(USE_PBR) + color.rgb = pow(color.rgb, vec3(2.2)); #endif vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb; @@ -46,8 +46,8 @@ void main() color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0); -#if defined(r_tonemapGamma) - color.rgb = pow(color.rgb, vec3(1.0 / r_tonemapGamma)); +#if defined(USE_PBR) + color.rgb = pow(color.rgb, vec3(1.0 / 2.2)); #endif gl_FragColor = color; diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index 7e5493f3..2238cdaf 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -142,7 +142,7 @@ static void R_ColorShiftLightingFloats(float in[4], float out[4], float scale ) float r, g, b; #if defined(USE_OVERBRIGHT) - scale *= pow(2.0f, r_mapOverBrightBits->integer - tr.overbrightBits); + scale *= 1 << (r_mapOverBrightBits->integer - tr.overbrightBits); #endif r = in[0] * scale; @@ -2763,7 +2763,7 @@ void R_LoadLightGrid( lump_t *l ) { if (hdrLightGrid) { #if defined(USE_OVERBRIGHT) - float lightScale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits); + float lightScale = 1 << (r_mapOverBrightBits->integer - tr.overbrightBits); #else float lightScale = 1.0f; #endif diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index eaa7c8f5..f8637a66 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -322,17 +322,8 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha Q_strcat(dest, size, va("#ifndef r_FBufScale\n#define r_FBufScale vec2(%f, %f)\n#endif\n", fbufWidthScale, fbufHeightScale)); - if (r_materialGamma->value != 1.0f) - Q_strcat(dest, size, va("#ifndef r_materialGamma\n#define r_materialGamma %f\n#endif\n", r_materialGamma->value)); - - if (r_lightGamma->value != 1.0f) - Q_strcat(dest, size, va("#ifndef r_lightGamma\n#define r_lightGamma %f\n#endif\n", r_lightGamma->value)); - - if (r_framebufferGamma->value != 1.0f) - Q_strcat(dest, size, va("#ifndef r_framebufferGamma\n#define r_framebufferGamma %f\n#endif\n", r_framebufferGamma->value)); - - if (r_tonemapGamma->value != 1.0f) - Q_strcat(dest, size, va("#ifndef r_tonemapGamma\n#define r_tonemapGamma %f\n#endif\n", r_tonemapGamma->value)); + if (r_pbr->integer) + Q_strcat(dest, size, "#define USE_PBR\n"); if (extra) { @@ -1009,12 +1000,6 @@ void GLSL_InitGPUShaders(void) extradefines[0] = '\0'; - if (r_specularIsMetallic->value) - Q_strcat(extradefines, 1024, "#define SPECULAR_IS_METALLIC\n"); - - if (r_glossIsRoughness->value) - Q_strcat(extradefines, 1024, "#define GLOSS_IS_ROUGHNESS\n"); - if (r_dlightMode->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOWMAP\n"); diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 88335b7a..47843fe2 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -2859,6 +2859,11 @@ void R_SetColorMappings( void ) { tr.overbrightBits = 0; } + // don't allow more overbright bits than map overbright bits + if ( tr.overbrightBits > r_mapOverBrightBits->integer ) { + tr.overbrightBits = r_mapOverBrightBits->integer; + } + tr.identityLight = 1.0f / ( 1 << tr.overbrightBits ); tr.identityLightByte = 255 * tr.identityLight; diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 0c02f887..18eecf0b 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -131,11 +131,6 @@ cvar_t *r_forceAutoExposure; cvar_t *r_forceAutoExposureMin; cvar_t *r_forceAutoExposureMax; -cvar_t *r_materialGamma; -cvar_t *r_lightGamma; -cvar_t *r_framebufferGamma; -cvar_t *r_tonemapGamma; - cvar_t *r_depthPrepass; cvar_t *r_ssao; @@ -145,8 +140,7 @@ cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; cvar_t *r_cubemapSize; -cvar_t *r_specularIsMetallic; -cvar_t *r_glossIsRoughness; +cvar_t *r_pbr; cvar_t *r_baseNormalX; cvar_t *r_baseNormalY; cvar_t *r_baseParallax; @@ -1141,7 +1135,7 @@ void R_Register( void ) r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); - r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH ); + r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE ); r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT ); r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT ); r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT ); @@ -1154,11 +1148,6 @@ void R_Register( void ) r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT ); - r_materialGamma = ri.Cvar_Get( "r_materialGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); - r_lightGamma = ri.Cvar_Get( "r_lightGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); - r_framebufferGamma = ri.Cvar_Get( "r_framebufferGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); - r_tonemapGamma = ri.Cvar_Get( "r_tonemapGamma", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); - r_depthPrepass = ri.Cvar_Get( "r_depthPrepass", "1", CVAR_ARCHIVE ); r_ssao = ri.Cvar_Get( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE ); @@ -1168,8 +1157,7 @@ void R_Register( void ) r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH ); - r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH); + r_pbr = ri.Cvar_Get("r_pbr", "0", CVAR_ARCHIVE | CVAR_LATCH); r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseNormalY = ri.Cvar_Get( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH ); r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index f56d5f51..9da87e6e 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1778,11 +1778,6 @@ extern cvar_t *r_forceAutoExposureMax; extern cvar_t *r_cameraExposure; -extern cvar_t *r_materialGamma; -extern cvar_t *r_lightGamma; -extern cvar_t *r_framebufferGamma; -extern cvar_t *r_tonemapGamma; - extern cvar_t *r_depthPrepass; extern cvar_t *r_ssao; @@ -1792,8 +1787,7 @@ extern cvar_t *r_deluxeMapping; extern cvar_t *r_parallaxMapping; extern cvar_t *r_cubeMapping; extern cvar_t *r_cubemapSize; -extern cvar_t *r_specularIsMetallic; -extern cvar_t *r_glossIsRoughness; +extern cvar_t *r_pbr; extern cvar_t *r_baseNormalX; extern cvar_t *r_baseNormalY; extern cvar_t *r_baseParallax; diff --git a/src/renderergl2/tr_scene.c b/src/renderergl2/tr_scene.c index 7e326a88..2578e7b9 100644 --- a/src/renderergl2/tr_scene.c +++ b/src/renderergl2/tr_scene.c @@ -337,7 +337,7 @@ void RE_BeginScene(const refdef_t *fd) else { #if defined(USE_OVERBRIGHT) - float scale = pow(2, r_mapOverBrightBits->integer - tr.overbrightBits - 8); + float scale = (1 << (r_mapOverBrightBits->integer - tr.overbrightBits)) / 255.0f;; #else float scale = (1 << r_mapOverBrightBits->integer) / 255.0f; #endif diff --git a/src/renderergl2/tr_shader.c b/src/renderergl2/tr_shader.c index b4a120ca..2cac0495 100644 --- a/src/renderergl2/tr_shader.c +++ b/src/renderergl2/tr_shader.c @@ -935,9 +935,18 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) ri.Printf( PRINT_WARNING, "WARNING: missing parameter for specular reflectance in shader '%s'\n", shader.name ); continue; } - stage->specularScale[0] = - stage->specularScale[1] = - stage->specularScale[2] = atof( token ); + + if (r_pbr->integer) + { + // interpret specularReflectance < 0.5 as nonmetal + stage->specularScale[1] = (atof(token) < 0.5f) ? 0.0f : 1.0f; + } + else + { + stage->specularScale[0] = + stage->specularScale[1] = + stage->specularScale[2] = atof( token ); + } } // // specularExponent @@ -955,8 +964,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) exponent = atof( token ); - if (r_glossIsRoughness->integer) - stage->specularScale[3] = powf(2.0f / (exponent + 2.0), 0.25); + if (r_pbr->integer) + stage->specularScale[0] = 1.0f - powf(2.0f / (exponent + 2.0), 0.25); else { // Change shininess to gloss @@ -981,8 +990,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) gloss = atof(token); - if (r_glossIsRoughness->integer) - stage->specularScale[3] = exp2f(-3.0f * gloss); + if (r_pbr->integer) + stage->specularScale[0] = 1.0f - exp2f(-3.0f * gloss); else stage->specularScale[3] = gloss; } @@ -1002,8 +1011,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) roughness = atof(token); - if (r_glossIsRoughness->integer) - stage->specularScale[3] = roughness; + if (r_pbr->integer) + stage->specularScale[0] = 1.0 - roughness; else { if (roughness >= 0.125) @@ -1063,6 +1072,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } // // specularScale + // or specularScale with r_pbr 1 // or specularScale // or specularScale // @@ -1089,10 +1099,19 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) token = COM_ParseExt(text, qfalse); if ( token[0] == 0 ) { - // two values, rgb then gloss - stage->specularScale[3] = stage->specularScale[1]; - stage->specularScale[1] = - stage->specularScale[2] = stage->specularScale[0]; + if (r_pbr->integer) + { + // two values, metallic then smoothness + float smoothness = stage->specularScale[1]; + stage->specularScale[1] = (stage->specularScale[0] < 0.5f) ? 0.0f : 1.0f; + stage->specularScale[0] = smoothness; + } + { + // two values, rgb then gloss + stage->specularScale[3] = stage->specularScale[1]; + stage->specularScale[1] = + stage->specularScale[2] = stage->specularScale[0]; + } continue; } @@ -2858,10 +2877,17 @@ static void InitShader( const char *name, int lightmapIndex ) { // default normal/specular VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f); - stages[i].specularScale[0] = - stages[i].specularScale[1] = - stages[i].specularScale[2] = r_baseSpecular->value; - stages[i].specularScale[3] = r_baseGloss->value; + if (r_pbr->integer) + { + stages[i].specularScale[0] = r_baseGloss->value; + } + else + { + stages[i].specularScale[0] = + stages[i].specularScale[1] = + stages[i].specularScale[2] = r_baseSpecular->value; + stages[i].specularScale[3] = r_baseGloss->value; + } } } -- cgit From e4a4b0b57899bde1f35565e18bcb9bb1b06f6320 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 10 Feb 2016 16:25:32 -0800 Subject: OpenGL2: Add named cubemaps and per-map env.json parsing. --- src/qcommon/json.h | 353 +++++++++++++++++++++++++++++++++++++++++++ src/renderergl2/tr_backend.c | 11 +- src/renderergl2/tr_bsp.c | 97 +++++++++++- src/renderergl2/tr_local.h | 1 + src/renderergl2/tr_main.c | 2 +- 5 files changed, 458 insertions(+), 6 deletions(-) create mode 100644 src/qcommon/json.h diff --git a/src/qcommon/json.h b/src/qcommon/json.h new file mode 100644 index 00000000..cfc5b3ca --- /dev/null +++ b/src/qcommon/json.h @@ -0,0 +1,353 @@ +/* +=========================================================================== +Copyright (C) 2016 James Canete + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +=========================================================================== +*/ + +#ifndef JSON_H +#define JSON_H + +enum +{ + JSONTYPE_STRING, // string + JSONTYPE_OBJECT, // object + JSONTYPE_ARRAY, // array + JSONTYPE_VALUE, // number, true, false, or null + JSONTYPE_ERROR // out of data +}; + +// -------------------------------------------------------------------------- +// Array Functions +// -------------------------------------------------------------------------- + +// Get pointer to first value in array +// When given pointer to an array, returns pointer to the first +// returns NULL if array is empty or not an array. +const char *JSON_ArrayGetFirstValue(const char *json, const char *jsonEnd); + +// Get pointer to next value in array +// When given pointer to a value, returns pointer to the next value +// returns NULL when no next value. +const char *JSON_ArrayGetNextValue(const char *json, const char *jsonEnd); + +// Get pointers to values in an array +// returns 0 if not an array, array is empty, or out of data +// returns number of values in the array and copies into index if successful +unsigned int JSON_ArrayGetIndex(const char *json, const char *jsonEnd, const char **indexes, unsigned int numIndexes); + +// Get pointer to indexed value from array +// returns NULL if not an array, no index, or out of data +const char *JSON_ArrayGetValue(const char *json, const char *jsonEnd, unsigned int index); + +// -------------------------------------------------------------------------- +// Object Functions +// -------------------------------------------------------------------------- + +// Get pointer to named value from object +// returns NULL if not an object, name not found, or out of data +const char *JSON_ObjectGetNamedValue(const char *json, const char *jsonEnd, const char *name); + +// -------------------------------------------------------------------------- +// Value Functions +// -------------------------------------------------------------------------- + +// Get type of value +// returns JSONTYPE_ERROR if out of data +unsigned int JSON_ValueGetType(const char *json, const char *jsonEnd); + +// Get value as string +// returns 0 if out of data +// returns length and copies into string if successful, including terminating nul. +// string values are stripped of enclosing quotes but not escaped +unsigned int JSON_ValueGetString(const char *json, const char *jsonEnd, char *outString, unsigned int stringLen); + +// Get value as appropriate type +// returns 0 if value is false, value is null, or out of data +// returns 1 if value is true +// returns value otherwise +double JSON_ValueGetDouble(const char *json, const char *jsonEnd); +float JSON_ValueGetFloat(const char *json, const char *jsonEnd); +int JSON_ValueGetInt(const char *json, const char *jsonEnd); + +#endif + +#ifdef JSON_IMPLEMENTATION +#include + +// -------------------------------------------------------------------------- +// Internal Functions +// -------------------------------------------------------------------------- + +static const char *JSON_SkipSeparators(const char *json, const char *jsonEnd); +static const char *JSON_SkipString(const char *json, const char *jsonEnd); +static const char *JSON_SkipStruct(const char *json, const char *jsonEnd); +static const char *JSON_SkipValue(const char *json, const char *jsonEnd); +static const char *JSON_SkipValueAndSeparators(const char *json, const char *jsonEnd); + +#define IS_SEPARATOR(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r' || (x) == ',' || (x) == ':') +#define IS_STRUCT_OPEN(x) ((x) == '{' || (x) == '[') +#define IS_STRUCT_CLOSE(x) ((x) == '}' || (x) == ']') + +static const char *JSON_SkipSeparators(const char *json, const char *jsonEnd) +{ + while (json < jsonEnd && IS_SEPARATOR(*json)) + json++; + + return json; +} + +static const char *JSON_SkipString(const char *json, const char *jsonEnd) +{ + for (json++; json < jsonEnd && *json != '"'; json++) + if (*json == '\\') + json++; + + return (json + 1 > jsonEnd) ? jsonEnd : json + 1; +} + +static const char *JSON_SkipStruct(const char *json, const char *jsonEnd) +{ + json = JSON_SkipSeparators(json + 1, jsonEnd); + while (json < jsonEnd && !IS_STRUCT_CLOSE(*json)) + json = JSON_SkipValueAndSeparators(json, jsonEnd); + + return (json + 1 > jsonEnd) ? jsonEnd : json + 1; +} + +static const char *JSON_SkipValue(const char *json, const char *jsonEnd) +{ + if (json >= jsonEnd) + return jsonEnd; + else if (*json == '"') + json = JSON_SkipString(json, jsonEnd); + else if (IS_STRUCT_OPEN(*json)) + json = JSON_SkipStruct(json, jsonEnd); + else + { + while (json < jsonEnd && !IS_SEPARATOR(*json) && !IS_STRUCT_CLOSE(*json)) + json++; + } + + return json; +} + +static const char *JSON_SkipValueAndSeparators(const char *json, const char *jsonEnd) +{ + json = JSON_SkipValue(json, jsonEnd); + return JSON_SkipSeparators(json, jsonEnd); +} + +// returns 0 if value requires more parsing, 1 if no more data/false/null, 2 if true +static unsigned int JSON_NoParse(const char *json, const char *jsonEnd) +{ + if (!json || json >= jsonEnd || *json == 'f' || *json == 'n') + return 1; + + if (*json == 't') + return 2; + + return 0; +} + +// -------------------------------------------------------------------------- +// Array Functions +// -------------------------------------------------------------------------- + +const char *JSON_ArrayGetFirstValue(const char *json, const char *jsonEnd) +{ + if (!json || json >= jsonEnd || !IS_STRUCT_OPEN(*json)) + return NULL; + + json = JSON_SkipSeparators(json + 1, jsonEnd); + + return (json >= jsonEnd || IS_STRUCT_CLOSE(*json)) ? NULL : json; +} + +const char *JSON_ArrayGetNextValue(const char *json, const char *jsonEnd) +{ + if (!json || json >= jsonEnd || IS_STRUCT_CLOSE(*json)) + return NULL; + + json = JSON_SkipValueAndSeparators(json, jsonEnd); + + return (json >= jsonEnd || IS_STRUCT_CLOSE(*json)) ? NULL : json; +} + +unsigned int JSON_ArrayGetIndex(const char *json, const char *jsonEnd, const char **indexes, unsigned int numIndexes) +{ + unsigned int length = 0; + + for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json; json = JSON_ArrayGetNextValue(json, jsonEnd)) + { + if (indexes && numIndexes) + { + *indexes++ = json; + numIndexes--; + } + length++; + } + + return length; +} + +const char *JSON_ArrayGetValue(const char *json, const char *jsonEnd, unsigned int index) +{ + for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json && index; json = JSON_ArrayGetNextValue(json, jsonEnd)) + index--; + + return json; +} + +// -------------------------------------------------------------------------- +// Object Functions +// -------------------------------------------------------------------------- + +const char *JSON_ObjectGetNamedValue(const char *json, const char *jsonEnd, const char *name) +{ + unsigned int nameLen = strlen(name); + + for (json = JSON_ArrayGetFirstValue(json, jsonEnd); json; json = JSON_ArrayGetNextValue(json, jsonEnd)) + { + if (*json == '"') + { + const char *thisNameStart, *thisNameEnd; + + thisNameStart = json + 1; + json = JSON_SkipString(json, jsonEnd); + thisNameEnd = json - 1; + json = JSON_SkipSeparators(json, jsonEnd); + + if ((unsigned int)(thisNameEnd - thisNameStart) == nameLen) + if (strncmp(thisNameStart, name, nameLen) == 0) + return json; + } + } + + return NULL; +} + +// -------------------------------------------------------------------------- +// Value Functions +// -------------------------------------------------------------------------- + +unsigned int JSON_ValueGetType(const char *json, const char *jsonEnd) +{ + if (!json || json >= jsonEnd) + return JSONTYPE_ERROR; + else if (*json == '"') + return JSONTYPE_STRING; + else if (*json == '{') + return JSONTYPE_OBJECT; + else if (*json == '[') + return JSONTYPE_ARRAY; + + return JSONTYPE_VALUE; +} + +unsigned int JSON_ValueGetString(const char *json, const char *jsonEnd, char *outString, unsigned int stringLen) +{ + const char *stringEnd, *stringStart; + + if (!json) + { + *outString = '\0'; + return 0; + } + + stringStart = json; + stringEnd = JSON_SkipValue(stringStart, jsonEnd); + if (stringEnd >= jsonEnd) + { + *outString = '\0'; + return 0; + } + + // skip enclosing quotes if they exist + if (*stringStart == '"') + stringStart++; + + if (*(stringEnd - 1) == '"') + stringEnd--; + + stringLen--; + if (stringLen > stringEnd - stringStart) + stringLen = stringEnd - stringStart; + + json = stringStart; + while (stringLen--) + *outString++ = *json++; + *outString = '\0'; + + return stringEnd - stringStart; +} + +double JSON_ValueGetDouble(const char *json, const char *jsonEnd) +{ + char cValue[256]; + double dValue = 0.0; + unsigned int np = JSON_NoParse(json, jsonEnd); + + if (np) + return (double)(np - 1); + + if (!JSON_ValueGetString(json, jsonEnd, cValue, 256)) + return 0.0; + + sscanf(cValue, "%lf", &dValue); + + return dValue; +} + +float JSON_ValueGetFloat(const char *json, const char *jsonEnd) +{ + char cValue[256]; + float fValue = 0.0f; + unsigned int np = JSON_NoParse(json, jsonEnd); + + if (np) + return (float)(np - 1); + + if (!JSON_ValueGetString(json, jsonEnd, cValue, 256)) + return 0.0f; + + sscanf(cValue, "%f", &fValue); + + return fValue; +} + +int JSON_ValueGetInt(const char *json, const char *jsonEnd) +{ + char cValue[256]; + int iValue = 0; + unsigned int np = JSON_NoParse(json, jsonEnd); + + if (np) + return np - 1; + + if (!JSON_ValueGetString(json, jsonEnd, cValue, 256)) + return 0; + + sscanf(cValue, "%d", &iValue); + + return iValue; +} + +#undef IS_SEPARATOR +#undef IS_STRUCT_OPEN +#undef IS_STRUCT_CLOSE + +#endif diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index ae475b02..f7720443 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -1675,7 +1675,16 @@ const void *RB_ExportCubemaps(const void *data) p += sideSize; } - Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); + if (cubemap->name[0]) + { + COM_StripExtension(cubemap->name, filename, MAX_QPATH); + Q_strcat(filename, MAX_QPATH, ".dds"); + } + else + { + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i); + } + R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6); ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename); } diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index 2238cdaf..9a03f991 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -24,6 +24,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" +#define JSON_IMPLEMENTATION +#include "..\qcommon\json.h" +#undef JSON_IMPLEMENTATION + /* Loads and prepares a map file for scene rendering. @@ -2973,6 +2977,78 @@ qboolean R_ParseSpawnVars( char *spawnVarChars, int maxSpawnVarChars, int *numSp return qtrue; } +void R_LoadEnvironmentJson(const char *baseName) +{ + char filename[MAX_QPATH]; + + union { + char *c; + void *v; + } buffer; + char *bufferEnd; + + const char *cubemapArrayJson; + int filelen, i; + + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/env.json", baseName); + + filelen = ri.FS_ReadFile(filename, &buffer.v); + if (!buffer.c) + return; + bufferEnd = buffer.c + filelen; + + if (JSON_ValueGetType(buffer.c, bufferEnd) != JSONTYPE_OBJECT) + { + ri.Printf(PRINT_ALL, "Bad %s: does not start with a object\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + cubemapArrayJson = JSON_ObjectGetNamedValue(buffer.c, bufferEnd, "Cubemaps"); + if (!cubemapArrayJson) + { + ri.Printf(PRINT_ALL, "Bad %s: no Cubemaps\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + if (JSON_ValueGetType(cubemapArrayJson, bufferEnd) != JSONTYPE_ARRAY) + { + ri.Printf(PRINT_ALL, "Bad %s: Cubemaps not an array\n", filename); + ri.FS_FreeFile(buffer.v); + return; + } + + tr.numCubemaps = JSON_ArrayGetIndex(cubemapArrayJson, bufferEnd, NULL, 0); + tr.cubemaps = ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); + memset(tr.cubemaps, 0, tr.numCubemaps * sizeof(*tr.cubemaps)); + + for (i = 0; i < tr.numCubemaps; i++) + { + cubemap_t *cubemap = &tr.cubemaps[i]; + const char *cubemapJson, *keyValueJson, *indexes[3]; + int j; + + cubemapJson = JSON_ArrayGetValue(cubemapArrayJson, bufferEnd, i); + + keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Name"); + if (!JSON_ValueGetString(keyValueJson, bufferEnd, cubemap->name, MAX_QPATH)) + cubemap->name[0] = '\0'; + + keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Position"); + JSON_ArrayGetIndex(keyValueJson, bufferEnd, indexes, 3); + for (j = 0; j < 3; j++) + cubemap->origin[j] = JSON_ValueGetFloat(indexes[j], bufferEnd); + + cubemap->parallaxRadius = 1000.0f; + keyValueJson = JSON_ObjectGetNamedValue(cubemapJson, bufferEnd, "Radius"); + if (keyValueJson) + cubemap->parallaxRadius = JSON_ValueGetFloat(keyValueJson, bufferEnd); + } + + ri.FS_FreeFile(buffer.v); +} + void R_LoadCubemapEntities(char *cubemapEntityName) { char spawnVarChars[2048]; @@ -3004,16 +3080,21 @@ void R_LoadCubemapEntities(char *cubemapEntityName) while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars)) { int i; + char name[MAX_QPATH]; qboolean isCubemap = qfalse; qboolean originSet = qfalse; vec3_t origin; float parallaxRadius = 1000.0f; + name[0] = '\0'; for (i = 0; i < numSpawnVars; i++) { if (!Q_stricmp(spawnVars[i][0], "classname") && !Q_stricmp(spawnVars[i][1], cubemapEntityName)) isCubemap = qtrue; + if (!Q_stricmp(spawnVars[i][0], "name")) + Q_strncpyz(name, spawnVars[i][1], MAX_QPATH); + if (!Q_stricmp(spawnVars[i][0], "origin")) { sscanf(spawnVars[i][1], "%f %f %f", &origin[0], &origin[1], &origin[2]); @@ -3027,9 +3108,10 @@ void R_LoadCubemapEntities(char *cubemapEntityName) if (isCubemap && originSet) { - //ri.Printf(PRINT_ALL, "cubemap at %f %f %f\n", origin[0], origin[1], origin[2]); - VectorCopy(origin, tr.cubemaps[numCubemaps].origin); - tr.cubemaps[numCubemaps].parallaxRadius = parallaxRadius; + cubemap_t *cubemap = &tr.cubemaps[numCubemaps]; + Q_strncpyz(cubemap->name, name, MAX_QPATH); + VectorCopy(origin, cubemap->origin); + cubemap->parallaxRadius = parallaxRadius; numCubemaps++; } } @@ -3420,7 +3502,14 @@ void RE_LoadWorldMap( const char *name ) { // load cubemaps if (r_cubeMapping->integer) { - R_LoadCubemapEntities("misc_cubemap"); + // Try loading an env.json file first + R_LoadEnvironmentJson(s_worldData.baseName); + + if (!tr.numCubemaps) + { + R_LoadCubemapEntities("misc_cubemap"); + } + if (!tr.numCubemaps) { // use deathmatch spawn points as cubemaps diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 9da87e6e..62bf1e03 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -60,6 +60,7 @@ typedef unsigned int glIndex_t; #define USE_OVERBRIGHT typedef struct cubemap_s { + char name[MAX_QPATH]; vec3_t origin; float parallaxRadius; image_t *image; diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index 63fea5ac..f4261033 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -2937,7 +2937,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) // only print message for first side if (directed[0] + directed[1] + directed[2] == 0 && cubemapSide == 0) { - ri.Printf(PRINT_ALL, "cubemap %d (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]); + ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]); } } -- cgit From 93a760743f4949330e301ca6729c1d88ba8484c1 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 12 Feb 2016 18:34:31 -0800 Subject: OpenGL2: Typos. --- src/renderergl2/tr_bsp.c | 2 +- src/renderergl2/tr_scene.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/renderergl2/tr_bsp.c b/src/renderergl2/tr_bsp.c index 9a03f991..8429d8cb 100644 --- a/src/renderergl2/tr_bsp.c +++ b/src/renderergl2/tr_bsp.c @@ -25,7 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #define JSON_IMPLEMENTATION -#include "..\qcommon\json.h" +#include "../qcommon/json.h" #undef JSON_IMPLEMENTATION /* diff --git a/src/renderergl2/tr_scene.c b/src/renderergl2/tr_scene.c index 2578e7b9..24108046 100644 --- a/src/renderergl2/tr_scene.c +++ b/src/renderergl2/tr_scene.c @@ -337,7 +337,7 @@ void RE_BeginScene(const refdef_t *fd) else { #if defined(USE_OVERBRIGHT) - float scale = (1 << (r_mapOverBrightBits->integer - tr.overbrightBits)) / 255.0f;; + float scale = (1 << (r_mapOverBrightBits->integer - tr.overbrightBits)) / 255.0f; #else float scale = (1 << r_mapOverBrightBits->integer) / 255.0f; #endif -- cgit From 3043117bd95828ddc350a296f93489869474c4ea Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 17 Feb 2016 19:49:21 -0800 Subject: OpenGL2: Fix some GL errors and no sun shadows on older OpenGLs. --- src/renderergl2/tr_dsa.c | 2 +- src/renderergl2/tr_fbo.c | 8 ++++++-- src/renderergl2/tr_image.c | 4 +--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/renderergl2/tr_dsa.c b/src/renderergl2/tr_dsa.c index a766263a..9cd481bd 100644 --- a/src/renderergl2/tr_dsa.c +++ b/src/renderergl2/tr_dsa.c @@ -210,7 +210,7 @@ void GL_BindNullFramebuffers() qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); glDsaState.drawFramebuffer = glDsaState.readFramebuffer = 0; qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - glDsaState.readFramebuffer = 0; + glDsaState.renderbuffer = 0; } void GL_BindFramebuffer(GLenum target, GLuint framebuffer) diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index 59b17032..12293766 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -251,7 +251,7 @@ FBO_Init void FBO_Init(void) { int i; - int hdrFormat, multisample; + int hdrFormat, multisample = 0; ri.Printf(PRINT_ALL, "------- FBO_Init -------\n"); @@ -268,7 +268,8 @@ void FBO_Init(void) if (r_hdr->integer && glRefConfig.framebufferObject && glRefConfig.textureFloat) hdrFormat = GL_RGBA16F_ARB; - qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample); + if (glRefConfig.framebufferMultisample) + qglGetIntegerv(GL_MAX_SAMPLES_EXT, &multisample); if (r_ext_framebuffer_multisample->integer < multisample) multisample = r_ext_framebuffer_multisample->integer; @@ -334,6 +335,9 @@ void FBO_Init(void) for ( i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); + // FIXME: this next line wastes 16mb with 4x1024x1024 sun shadow maps, skip if OpenGL 4.3+ or ARB_framebuffer_no_attachments + // This at least gets sun shadows working on older GPUs (Intel) + FBO_CreateBuffer(tr.sunShadowFbo[i], GL_RGBA8, 0, 0); FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.sunShadowFbo[i]); } diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 47843fe2..d567193b 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -116,7 +116,7 @@ void GL_TextureMode( const char *string ) { // change all the existing mipmap texture objects for ( i = 0 ; i < tr.numImages ; i++ ) { glt = tr.images[ i ]; - if ( glt->flags & IMGFLAG_MIPMAP ) { + if ( glt->flags & IMGFLAG_MIPMAP && !(glt->flags & IMGFLAG_CUBEMAP)) { qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTextureParameterf(glt->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); } @@ -2818,8 +2818,6 @@ void R_CreateBuiltinImages( void ) { for ( x = 0; x < 4; x++) { tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); - qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); qglTextureParameterf(tr.sunShadowDepthImage[x]->texnum, GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } -- cgit From fdf6b74c210f7cc1fd54472308fc61c9341c4de1 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 17 Feb 2016 20:06:18 -0800 Subject: OpenGL2: Shader optimization, and add dither to tonemap. --- src/renderergl2/glsl/calclevels4x_fp.glsl | 2 +- src/renderergl2/glsl/lightall_fp.glsl | 106 +++++++++++------------------- src/renderergl2/glsl/lightall_vp.glsl | 21 ++++-- src/renderergl2/glsl/tonemap_fp.glsl | 7 +- src/renderergl2/tr_shade.c | 14 +++- 5 files changed, 76 insertions(+), 74 deletions(-) diff --git a/src/renderergl2/glsl/calclevels4x_fp.glsl b/src/renderergl2/glsl/calclevels4x_fp.glsl index 0d298b62..8246c4b3 100644 --- a/src/renderergl2/glsl/calclevels4x_fp.glsl +++ b/src/renderergl2/glsl/calclevels4x_fp.glsl @@ -15,7 +15,7 @@ vec3 GetValues(vec2 offset, vec3 current) #ifdef FIRST_PASS #if defined(USE_PBR) - minAvgMax = pow(minAvgMax, vec3(2.2)); + minAvgMax *= minAvgMax; #endif float lumi = max(dot(LUMINANCE_VECTOR, minAvgMax), 0.000001); diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index eb8ba900..6a0a5155 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -29,11 +29,6 @@ uniform samplerCube u_CubeMap; uniform vec4 u_EnableTextures; #endif -#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) -uniform vec3 u_DirectedLight; -uniform vec3 u_AmbientLight; -#endif - #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) uniform vec3 u_PrimaryLightColor; uniform vec3 u_PrimaryLightAmbient; @@ -53,6 +48,9 @@ uniform vec4 u_CubeMapInfo; varying vec4 var_TexCoords; varying vec4 var_Color; +#if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) +varying vec4 var_ColorAmbient; +#endif #if (defined(USE_LIGHT) && !defined(USE_FAST_LIGHT)) #if defined(USE_VERT_TANGENT_SPACE) @@ -150,7 +148,7 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) } #endif -vec3 CalcDiffuse(vec3 diffuseAlbedo, float EH, float NH, float roughness) +vec3 CalcDiffuse(vec3 diffuseAlbedo, float NH, float EH, float roughness) { #if defined(USE_BURLEY) // modified from https://disney-animation.s3.amazonaws.com/library/s2012_pbs_disney_brdf_notes_v2.pdf @@ -171,7 +169,7 @@ vec3 EnvironmentBRDF(float roughness, float NE, vec3 specular) return vec3(v) + specular; } -vec3 CalcSpecular(vec3 specular, float NH, float NL, float NE, float EH, float roughness) +vec3 CalcSpecular(vec3 specular, float NH, float EH, float roughness) { // from http://community.arm.com/servlet/JiveServlet/download/96891546-19496/siggraph2015-mmg-renaldas-slides.pdf float rr = roughness*roughness; @@ -220,7 +218,7 @@ mat3 cotangent_frame( vec3 N, vec3 p, vec2 uv ) void main() { - vec3 viewDir, lightColor, ambientColor; + vec3 viewDir, lightColor, ambientColor, reflectance; vec3 L, N, E, H; float NL, NH, NE, EH, attenuation; @@ -232,21 +230,20 @@ void main() mat3 tangentToWorld = cotangent_frame(var_Normal, -var_ViewDir, var_TexCoords.xy); viewDir = var_ViewDir; #endif - E = normalize(viewDir); - - L = var_LightDir.xyz; - #if defined(USE_DELUXEMAP) - L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y; - #endif - float sqrLightDist = dot(L, L); #endif + lightColor = var_Color.rgb; + #if defined(USE_LIGHTMAP) vec4 lightmapColor = texture2D(u_LightMap, var_TexCoords.zw); #if defined(RGBM_LIGHTMAP) lightmapColor.rgb *= lightmapColor.a; #endif + #if defined(USE_PBR) && !defined(USE_FAST_LIGHT) + lightmapColor.rgb *= lightmapColor.rgb; + #endif + lightColor *= lightmapColor.rgb; #endif vec2 texCoords = var_TexCoords.xy; @@ -262,23 +259,17 @@ void main() vec4 diffuse = texture2D(u_DiffuseMap, texCoords); #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) - #if defined(USE_LIGHTMAP) - lightColor = lightmapColor.rgb * var_Color.rgb; - ambientColor = vec3(0.0); - attenuation = 1.0; - #elif defined(USE_LIGHT_VECTOR) - lightColor = u_DirectedLight * var_Color.rgb; - ambientColor = u_AmbientLight * var_Color.rgb; - attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist); - #elif defined(USE_LIGHT_VERTEX) - lightColor = var_Color.rgb; - ambientColor = vec3(0.0); - attenuation = 1.0; + L = var_LightDir.xyz; + #if defined(USE_DELUXEMAP) + L += (texture2D(u_DeluxeMap, var_TexCoords.zw).xyz - vec3(0.5)) * u_EnableTextures.y; #endif + float sqrLightDist = dot(L, L); + L /= sqrt(sqrLightDist); - #if defined(USE_PBR) - lightColor = pow(lightColor, vec3(2.2)); - ambientColor = pow(ambientColor, vec3(2.2)); + #if defined(USE_LIGHT_VECTOR) + attenuation = CalcLightAttenuation(float(var_LightDir.w > 0.0), var_LightDir.w / sqrLightDist); + #else + attenuation = 1.0; #endif #if defined(USE_NORMALMAP) @@ -295,21 +286,20 @@ void main() #endif N = normalize(N); - L /= sqrt(sqrLightDist); #if defined(USE_SHADOWMAP) vec2 shadowTex = gl_FragCoord.xy * r_FBufScale; float shadowValue = texture2D(u_ShadowMap, shadowTex).r; // surfaces not facing the light are always shadowed - shadowValue *= float(dot(var_Normal.xyz, var_PrimaryLightDir.xyz) > 0.0); + shadowValue *= clamp(dot(var_Normal.xyz, var_PrimaryLightDir.xyz), 0.0, 1.0); #if defined(SHADOWMAP_MODULATE) lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r; #endif #endif - #if defined(USE_LIGHTMAP) || defined(USE_LIGHT_VERTEX) + #if !defined(USE_LIGHT_VECTOR) ambientColor = lightColor; float surfNL = clamp(dot(var_Normal.xyz, L), 0.0, 1.0); @@ -320,9 +310,9 @@ void main() // Recover any unused light as ambient, in case attenuation is over 4x or // light is below the surface ambientColor = max(ambientColor - lightColor * surfNL, vec3(0.0)); + #else + ambientColor = var_ColorAmbient.rgb; #endif - - vec3 reflectance; NL = clamp(dot(N, L), 0.0, 1.0); NE = clamp(dot(N, E), 0.0, 1.0); @@ -332,32 +322,30 @@ void main() #else vec4 specular = vec4(1.0); #endif - specular *= u_SpecularScale; #if defined(USE_PBR) - diffuse.rgb = pow(diffuse.rgb, vec3(2.2)); + diffuse.rgb *= diffuse.rgb; #endif - float gloss = specular.a; #if defined(USE_PBR) + // diffuse rgb is base color + // specular red is smoothness + // specular green is metallicness float roughness = 1.0 - specular.r; + specular.rgb = specular.g * diffuse.rgb + vec3(0.04 - 0.04 * specular.g); + diffuse.rgb *= 1.0 - specular.g; #else - float roughness = exp2(-3.0 * gloss); - #endif + // diffuse rgb is diffuse + // specular rgb is specular reflectance at normal incidence + // specular alpha is gloss + float roughness = exp2(-3.0 * specular.a); - #if defined(USE_PBR) - // diffuse is actually base color, and green of specular is metallicness - float metallic = specular.g; - - specular.rgb = metallic * diffuse.rgb + vec3(0.04 - 0.04 * metallic); - diffuse.rgb *= 1.0 - metallic; - #else // adjust diffuse by specular reflectance, to maintain energy conservation diffuse.rgb *= vec3(1.0) - specular.rgb; #endif - reflectance = CalcDiffuse(diffuse.rgb, EH, NH, roughness); + reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness); gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); gl_FragColor.rgb += ambientColor * diffuse.rgb; @@ -371,11 +359,7 @@ void main() // from http://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ vec3 parallax = u_CubeMapInfo.xyz + u_CubeMapInfo.w * viewDir; - #if defined(USE_PBR) vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 * roughness).rgb * u_EnableTextures.w; - #else - vec3 cubeLightColor = textureCubeLod(u_CubeMap, R + parallax, 7.0 - gloss * 7.0).rgb * u_EnableTextures.w; - #endif // normalize cubemap based on lowest mip (~diffuse) // multiplying cubemap values by lighting below depends on either this or the cubemap being normalized at generation @@ -383,7 +367,7 @@ void main() //cubeLightColor /= dot(cubeLightDiffuse, vec3(0.2125, 0.7154, 0.0721)); #if defined(USE_PBR) - cubeLightColor = pow(cubeLightColor, vec3(2.2)); + cubeLightColor *= cubeLightColor; #endif // multiply cubemap values by lighting @@ -404,24 +388,19 @@ void main() //L2 /= sqrt(sqrLightDist); NL2 = clamp(dot(N, L2), 0.0, 1.0); - H2 = normalize(L2 + E); EH2 = clamp(dot(E, H2), 0.0, 1.0); NH2 = clamp(dot(N, H2), 0.0, 1.0); - reflectance = CalcSpecular(specular.rgb, NH2, NL2, NE, EH2, roughness); + reflectance = CalcSpecular(specular.rgb, NH2, EH2, roughness); // bit of a hack, with modulated shadowmaps, ignore diffuse #if !defined(SHADOWMAP_MODULATE) - reflectance += CalcDiffuse(diffuse.rgb, EH2, NH2, roughness); + reflectance += CalcDiffuse(diffuse.rgb, NH2, EH2, roughness); #endif lightColor = u_PrimaryLightColor; - #if defined(USE_PBR) - lightColor = pow(lightColor, vec3(2.2)); - #endif - #if defined(USE_SHADOWMAP) lightColor *= shadowValue; #endif @@ -433,15 +412,10 @@ void main() #endif #if defined(USE_PBR) - gl_FragColor.rgb = pow(gl_FragColor.rgb, vec3(1.0 / 2.2)); + gl_FragColor.rgb = sqrt(gl_FragColor.rgb); #endif #else - lightColor = var_Color.rgb; - - #if defined(USE_LIGHTMAP) - lightColor *= lightmapColor.rgb; - #endif gl_FragColor.rgb = diffuse.rgb * lightColor; diff --git a/src/renderergl2/glsl/lightall_vp.glsl b/src/renderergl2/glsl/lightall_vp.glsl index 59051d7c..783885e9 100644 --- a/src/renderergl2/glsl/lightall_vp.glsl +++ b/src/renderergl2/glsl/lightall_vp.glsl @@ -57,10 +57,8 @@ uniform float u_VertexLerp; #if defined(USE_LIGHT_VECTOR) uniform vec4 u_LightOrigin; uniform float u_LightRadius; - #if defined(USE_FAST_LIGHT) uniform vec3 u_DirectedLight; uniform vec3 u_AmbientLight; - #endif #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) @@ -71,6 +69,9 @@ uniform float u_PrimaryLightRadius; varying vec4 var_TexCoords; varying vec4 var_Color; +#if defined(USE_LIGHT_VECTOR) && !defined(USE_FAST_LIGHT) +varying vec4 var_ColorAmbient; +#endif #if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) #if defined(USE_VERT_TANGENT_SPACE) @@ -208,12 +209,24 @@ void main() var_Color = u_VertColor * attr_Color + u_BaseColor; -#if defined(USE_LIGHT_VECTOR) && defined(USE_FAST_LIGHT) +#if defined(USE_LIGHT_VECTOR) + #if defined(USE_FAST_LIGHT) float sqrLightDist = dot(L, L); - float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist); float NL = clamp(dot(normalize(normal), L) / sqrt(sqrLightDist), 0.0, 1.0); + float attenuation = CalcLightAttenuation(u_LightOrigin.w, u_LightRadius * u_LightRadius / sqrLightDist); var_Color.rgb *= u_DirectedLight * (attenuation * NL) + u_AmbientLight; + #else + var_ColorAmbient.rgb = u_AmbientLight * var_Color.rgb; + var_Color.rgb *= u_DirectedLight; + #if defined(USE_PBR) + var_ColorAmbient.rgb *= var_ColorAmbient.rgb; + #endif + #endif +#endif + +#if defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) && defined(USE_PBR) + var_Color.rgb *= var_Color.rgb; #endif #if defined(USE_PRIMARY_LIGHT) || defined(USE_SHADOWMAP) diff --git a/src/renderergl2/glsl/tonemap_fp.glsl b/src/renderergl2/glsl/tonemap_fp.glsl index 5d8841d6..9e24e24a 100644 --- a/src/renderergl2/glsl/tonemap_fp.glsl +++ b/src/renderergl2/glsl/tonemap_fp.glsl @@ -29,7 +29,7 @@ void main() vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color; #if defined(USE_PBR) - color.rgb = pow(color.rgb, vec3(2.2)); + color.rgb *= color.rgb; #endif vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb; @@ -47,8 +47,11 @@ void main() color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0); #if defined(USE_PBR) - color.rgb = pow(color.rgb, vec3(1.0 / 2.2)); + color.rgb = sqrt(color.rgb); #endif + // add a bit of dither to reduce banding + color.rgb += vec3(1.0/510.0 * mod(gl_FragCoord.x + gl_FragCoord.y, 2.0) - 1.0/1020.0); + gl_FragColor = color; } diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index f4d32a5e..b8295657 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -1274,7 +1274,19 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP); GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol); - GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol); + if (r_pbr->integer) + { + vec3_t color; + + color[0] = backEnd.refdef.sunCol[0] * backEnd.refdef.sunCol[0]; + color[1] = backEnd.refdef.sunCol[1] * backEnd.refdef.sunCol[1]; + color[2] = backEnd.refdef.sunCol[2] * backEnd.refdef.sunCol[2]; + GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, color); + } + else + { + GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol); + } GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir); } -- cgit From 5d1223366351d7ed9ee537d8f4245ab29b550d2c Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 7 Mar 2016 02:27:03 -0800 Subject: OpenGL2: Add r_shadowBlur. --- src/renderergl2/glsl/depthblur_fp.glsl | 20 ++++++--- src/renderergl2/tr_backend.c | 74 +++++++++++++++++----------------- src/renderergl2/tr_fbo.c | 8 ++++ src/renderergl2/tr_image.c | 7 +++- src/renderergl2/tr_init.c | 4 +- src/renderergl2/tr_local.h | 3 ++ 6 files changed, 73 insertions(+), 43 deletions(-) diff --git a/src/renderergl2/glsl/depthblur_fp.glsl b/src/renderergl2/glsl/depthblur_fp.glsl index 93895b4e..15f7be27 100644 --- a/src/renderergl2/glsl/depthblur_fp.glsl +++ b/src/renderergl2/glsl/depthblur_fp.glsl @@ -1,13 +1,13 @@ uniform sampler2D u_ScreenImageMap; uniform sampler2D u_ScreenDepthMap; -uniform vec4 u_ViewInfo; // zfar / znear, zfar +uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height varying vec2 var_ScreenTex; //float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024, 0.0033); float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); //float gauss[3] = float[3](0.60, 0.19, 0.0066); -#define GAUSS_SIZE 4 +#define BLUR_SIZE 4 float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { @@ -17,7 +17,7 @@ float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNea vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar) { - float scale = 1.0 / 256.0; + vec2 scale = u_ViewInfo.zw; #if defined(USE_HORIZONTAL_BLUR) vec2 direction = vec2(1.0, 0.0) * scale; @@ -27,22 +27,32 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa float depthCenter = zFar * getLinearDepth(depthMap, tex, zFarDivZNear); vec2 centerSlope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); - + +#if defined(USE_GAUSS) vec4 result = texture2D(imageMap, tex) * gauss[0]; float total = gauss[0]; +#else + vec4 result = texture2D(imageMap, tex); + float total = 1.0; +#endif int i, j; for (i = 0; i < 2; i++) { - for (j = 1; j < GAUSS_SIZE; j++) + for (j = 1; j < BLUR_SIZE; j++) { vec2 offset = direction * j; float depthSample = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear); float depthExpected = depthCenter + dot(centerSlope, offset); if(abs(depthSample - depthExpected) < 5.0) { +#if defined(USE_GAUSS) result += texture2D(imageMap, tex + offset) * gauss[j]; total += gauss[j]; +#else + result += texture2D(imageMap, tex + offset); + total += 1.0; +#endif } } diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index f7720443..e0715d04 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -957,6 +957,9 @@ const void *RB_DrawSurfs( const void *data ) { if (glRefConfig.framebufferObject && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && (r_depthPrepass->integer || (backEnd.viewParms.flags & VPF_DEPTHSHADOW))) { FBO_t *oldFbo = glState.currentFBO; + vec4_t viewInfo; + + VectorSet4(viewInfo, backEnd.viewParms.zFar / r_znear->value, backEnd.viewParms.zFar, 0.0, 0.0); backEnd.depthFill = qtrue; qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); @@ -1043,15 +1046,12 @@ const void *RB_DrawSurfs( const void *data ) { GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg); { - vec4_t viewInfo; vec3_t viewVector; float zmax = backEnd.viewParms.zFar; float ymax = zmax * tan(backEnd.viewParms.fovY * M_PI / 360.0f); float xmax = zmax * tan(backEnd.viewParms.fovX * M_PI / 360.0f); - float zmin = r_znear->value; - VectorScale(backEnd.refdef.viewaxis[0], zmax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWFORWARD, viewVector); VectorScale(backEnd.refdef.viewaxis[1], xmax, viewVector); @@ -1059,13 +1059,39 @@ const void *RB_DrawSurfs( const void *data ) { VectorScale(backEnd.refdef.viewaxis[2], ymax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWUP, viewVector); - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - GLSL_SetUniformVec4(&tr.shadowmaskShader, UNIFORM_VIEWINFO, viewInfo); } - RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); + + if (r_shadowBlur->integer) + { + viewInfo[2] = 1.0f / (float)(tr.screenScratchFbo->width); + viewInfo[3] = 1.0f / (float)(tr.screenScratchFbo->height); + + FBO_Bind(tr.screenScratchFbo); + + GLSL_BindProgram(&tr.depthBlurShader[0]); + + GL_BindToTMU(tr.screenShadowImage, TB_COLORMAP); + GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); + + GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); + + RB_InstantQuad2(quadVerts, texCoords); + + + FBO_Bind(tr.screenShadowFbo); + + GLSL_BindProgram(&tr.depthBlurShader[1]); + + GL_BindToTMU(tr.screenScratchImage, TB_COLORMAP); + GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); + + GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); + + RB_InstantQuad2(quadVerts, texCoords); + } } if (r_ssao->integer) @@ -1073,6 +1099,9 @@ const void *RB_DrawSurfs( const void *data ) { vec4_t quadVerts[4]; vec2_t texCoords[4]; + viewInfo[2] = 1.0f / (float)(tr.quarterImage[0]->width); + viewInfo[3] = 1.0f / (float)(tr.quarterImage[0]->height); + FBO_Bind(tr.quarterFbo[0]); qglViewport(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); @@ -1094,16 +1123,7 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.hdrDepthImage, TB_COLORMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.ssaoShader, UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.ssaoShader, UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); @@ -1118,16 +1138,7 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); @@ -1142,16 +1153,7 @@ const void *RB_DrawSurfs( const void *data ) { GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); - { - vec4_t viewInfo; - - float zmax = backEnd.viewParms.zFar; - float zmin = r_znear->value; - - VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); - - GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); - } + GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index 12293766..80d59f62 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -310,6 +310,14 @@ void FBO_Init(void) qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } + if (r_shadowBlur->integer) + { + tr.screenScratchFbo = FBO_Create("screenScratch", tr.screenScratchImage->width, tr.screenScratchImage->height); + FBO_AttachImage(tr.screenScratchFbo, tr.screenScratchImage, GL_COLOR_ATTACHMENT0_EXT, 0); + FBO_AttachImage(tr.screenScratchFbo, tr.renderDepthImage, GL_DEPTH_ATTACHMENT_EXT, 0); + R_CheckFBO(tr.screenScratchFbo); + } + if (r_drawSunRays->integer) { tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height); diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index d567193b..7e2d452e 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -2755,6 +2755,12 @@ void R_CreateBuiltinImages( void ) { tr.renderImage = R_CreateImage("_render", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, hdrFormat); + if (r_shadowBlur->integer) + tr.screenScratchImage = R_CreateImage("screenScratch", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, rgbFormat); + + if (r_shadowBlur->integer || r_ssao->integer) + tr.hdrDepthImage = R_CreateImage("*hdrDepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_INTENSITY32F_ARB); + if (r_drawSunRays->integer) tr.sunRaysImage = R_CreateImage("*sunRays", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, rgbFormat); @@ -2802,7 +2808,6 @@ void R_CreateBuiltinImages( void ) { if (r_ssao->integer) { tr.screenSsaoImage = R_CreateImage("*screenSsao", NULL, width / 2, height / 2, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); - tr.hdrDepthImage = R_CreateImage("*hdrDepth", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_INTENSITY32F_ARB); } if (r_shadows->integer == 4) diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 18eecf0b..06c4f0ae 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -161,6 +161,7 @@ cvar_t *r_sunlightMode; cvar_t *r_drawSunRays; cvar_t *r_sunShadows; cvar_t *r_shadowFilter; +cvar_t *r_shadowBlur; cvar_t *r_shadowMapSize; cvar_t *r_shadowCascadeZNear; cvar_t *r_shadowCascadeZFar; @@ -1180,7 +1181,8 @@ void R_Register( void ) r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); + r_shadowBlur = ri.Cvar_Get("r_shadowBlur", "0", CVAR_ARCHIVE | CVAR_LATCH); + r_shadowMapSize = ri.Cvar_Get("r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH); r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", CVAR_ARCHIVE | CVAR_LATCH ); r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", CVAR_ARCHIVE | CVAR_LATCH ); r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index 62bf1e03..e2a3fe17 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1521,6 +1521,7 @@ typedef struct { image_t *sunRaysImage; image_t *renderDepthImage; image_t *pshadowMaps[MAX_DRAWN_PSHADOWS]; + image_t *screenScratchImage; image_t *textureScratchImage[2]; image_t *quarterImage[2]; image_t *calcLevelsImage; @@ -1539,6 +1540,7 @@ typedef struct { FBO_t *sunRaysFbo; FBO_t *depthFbo; FBO_t *pshadowFbos[MAX_DRAWN_PSHADOWS]; + FBO_t *screenScratchFbo; FBO_t *textureScratchFbo[2]; FBO_t *quarterFbo[2]; FBO_t *calcLevelsFbo; @@ -1809,6 +1811,7 @@ extern cvar_t *r_sunlightMode; extern cvar_t *r_drawSunRays; extern cvar_t *r_sunShadows; extern cvar_t *r_shadowFilter; +extern cvar_t *r_shadowBlur; extern cvar_t *r_shadowMapSize; extern cvar_t *r_shadowCascadeZNear; extern cvar_t *r_shadowCascadeZFar; -- cgit From 7c858dafb7941be2ea6522a2a267252abf2d4fe7 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 7 Mar 2016 03:30:16 -0800 Subject: OpenGL2: Add r_glossType. --- src/renderergl2/glsl/lightall_fp.glsl | 14 ++++++++++++-- src/renderergl2/tr_glsl.c | 17 +++++++++++++++++ src/renderergl2/tr_init.c | 2 ++ src/renderergl2/tr_local.h | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index 6a0a5155..8edbebda 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -332,19 +332,29 @@ void main() // diffuse rgb is base color // specular red is smoothness // specular green is metallicness - float roughness = 1.0 - specular.r; + float gloss = specular.r; specular.rgb = specular.g * diffuse.rgb + vec3(0.04 - 0.04 * specular.g); diffuse.rgb *= 1.0 - specular.g; #else // diffuse rgb is diffuse // specular rgb is specular reflectance at normal incidence // specular alpha is gloss - float roughness = exp2(-3.0 * specular.a); + float gloss = specular.a; // adjust diffuse by specular reflectance, to maintain energy conservation diffuse.rgb *= vec3(1.0) - specular.rgb; #endif + #if defined(GLOSS_IS_GLOSS) + float roughness = exp2(-3.0 * gloss); + #elif defined(GLOSS_IS_SMOOTHNESS) + float roughness = 1.0 - gloss; + #elif defined(GLOSS_IS_ROUGHNESS) + float roughness = gloss; + #elif defined(GLOSS_IS_SHININESS) + float roughness = pow(2.0 / (8190.0 * gloss + 2.0), 0.25); + #endif + reflectance = CalcDiffuse(diffuse.rgb, NH, EH, roughness); gl_FragColor.rgb = lightColor * reflectance * (attenuation * NL); diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index f8637a66..b825c19e 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1057,6 +1057,23 @@ void GLSL_InitGPUShaders(void) if (r_cubeMapping->integer) Q_strcat(extradefines, 1024, "#define USE_CUBEMAP\n"); + + switch (r_glossType->integer) + { + case 0: + default: + Q_strcat(extradefines, 1024, "#define GLOSS_IS_GLOSS\n"); + break; + case 1: + Q_strcat(extradefines, 1024, "#define GLOSS_IS_SMOOTHNESS\n"); + break; + case 2: + Q_strcat(extradefines, 1024, "#define GLOSS_IS_ROUGHNESS\n"); + break; + case 3: + Q_strcat(extradefines, 1024, "#define GLOSS_IS_SHININESS\n"); + break; + } } if (i & LIGHTDEF_USE_SHADOWMAP) diff --git a/src/renderergl2/tr_init.c b/src/renderergl2/tr_init.c index 06c4f0ae..4f0a53f4 100644 --- a/src/renderergl2/tr_init.c +++ b/src/renderergl2/tr_init.c @@ -146,6 +146,7 @@ cvar_t *r_baseNormalY; cvar_t *r_baseParallax; cvar_t *r_baseSpecular; cvar_t *r_baseGloss; +cvar_t *r_glossType; cvar_t *r_mergeLightmaps; cvar_t *r_dlightMode; cvar_t *r_pshadowDist; @@ -1164,6 +1165,7 @@ void R_Register( void ) r_baseParallax = ri.Cvar_Get( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH ); r_baseSpecular = ri.Cvar_Get( "r_baseSpecular", "0.04", CVAR_ARCHIVE | CVAR_LATCH ); r_baseGloss = ri.Cvar_Get( "r_baseGloss", "0.3", CVAR_ARCHIVE | CVAR_LATCH ); + r_glossType = ri.Cvar_Get("r_glossType", "1", CVAR_ARCHIVE | CVAR_LATCH); r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE ); r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index e2a3fe17..d11c4870 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1796,6 +1796,7 @@ extern cvar_t *r_baseNormalY; extern cvar_t *r_baseParallax; extern cvar_t *r_baseSpecular; extern cvar_t *r_baseGloss; +extern cvar_t *r_glossType; extern cvar_t *r_dlightMode; extern cvar_t *r_pshadowDist; extern cvar_t *r_mergeLightmaps; -- cgit From c1ec25db8442cacf87df39d1e8e54b819b83a047 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 8 Mar 2016 18:30:51 -0800 Subject: OpenGL2: Speedup for SSAO & blur shaders, fix sunlight normals in lightall. --- src/renderergl2/glsl/depthblur_fp.glsl | 46 ++++++++++++++--------------- src/renderergl2/glsl/lightall_fp.glsl | 4 +-- src/renderergl2/glsl/ssao_fp.glsl | 54 +++++++++++++++++----------------- src/renderergl2/tr_backend.c | 7 +++-- 4 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/renderergl2/glsl/depthblur_fp.glsl b/src/renderergl2/glsl/depthblur_fp.glsl index 15f7be27..60a261c5 100644 --- a/src/renderergl2/glsl/depthblur_fp.glsl +++ b/src/renderergl2/glsl/depthblur_fp.glsl @@ -11,22 +11,23 @@ float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - float sampleZDivW = texture2D(depthMap, tex).r; - return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); + float sampleZDivW = texture2D(depthMap, tex).r; + return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } -vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar) +vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar, vec2 scale) { - vec2 scale = u_ViewInfo.zw; + float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear); + //scale /= zFarDivZNear * depthCenter; + //int blurSteps = int(float(BLUR_SIZE) / (zFarDivZNear * depthCenter)); #if defined(USE_HORIZONTAL_BLUR) - vec2 direction = vec2(1.0, 0.0) * scale; + vec2 direction = vec2(scale.x, 0.0); #else // if defined(USE_VERTICAL_BLUR) - vec2 direction = vec2(0.0, 1.0) * scale; + vec2 direction = vec2(0.0, scale.y); #endif - - float depthCenter = zFar * getLinearDepth(depthMap, tex, zFarDivZNear); - vec2 centerSlope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); + + vec2 slope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); #if defined(USE_GAUSS) vec4 result = texture2D(imageMap, tex) * gauss[0]; @@ -36,33 +37,32 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa float total = 1.0; #endif + float zLimit = 5.0 / zFar; int i, j; for (i = 0; i < 2; i++) { for (j = 1; j < BLUR_SIZE; j++) { vec2 offset = direction * j; - float depthSample = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear); - float depthExpected = depthCenter + dot(centerSlope, offset); - if(abs(depthSample - depthExpected) < 5.0) - { + float depthSample = getLinearDepth(depthMap, tex + offset, zFarDivZNear); + float depthExpected = depthCenter + dot(slope, offset); + float useSample = float(abs(depthSample - depthExpected) < zLimit); #if defined(USE_GAUSS) - result += texture2D(imageMap, tex + offset) * gauss[j]; - total += gauss[j]; + result += texture2D(imageMap, tex + offset) * (gauss[j] * useSample); + total += gauss[j] * useSample; #else - result += texture2D(imageMap, tex + offset); - total += 1.0; + result += texture2D(imageMap, tex + offset) * useSample; + total += useSample; #endif - } } - + direction = -direction; - } - + } + return result / total; } void main() -{ - gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y); +{ + gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw); } diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index 8edbebda..f16298a3 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -292,7 +292,7 @@ void main() float shadowValue = texture2D(u_ShadowMap, shadowTex).r; // surfaces not facing the light are always shadowed - shadowValue *= clamp(dot(var_Normal.xyz, var_PrimaryLightDir.xyz), 0.0, 1.0); + shadowValue *= clamp(dot(N, var_PrimaryLightDir.xyz), 0.0, 1.0); #if defined(SHADOWMAP_MODULATE) lightColor *= shadowValue * (1.0 - u_PrimaryLightAmbient.r) + u_PrimaryLightAmbient.r; @@ -330,7 +330,7 @@ void main() #if defined(USE_PBR) // diffuse rgb is base color - // specular red is smoothness + // specular red is gloss // specular green is metallicness float gloss = specular.r; specular.rgb = specular.g * diffuse.rgb + vec3(0.04 - 0.04 * specular.g); diff --git a/src/renderergl2/glsl/ssao_fp.glsl b/src/renderergl2/glsl/ssao_fp.glsl index 6263284c..84f18cb7 100644 --- a/src/renderergl2/glsl/ssao_fp.glsl +++ b/src/renderergl2/glsl/ssao_fp.glsl @@ -1,6 +1,6 @@ uniform sampler2D u_ScreenDepthMap; -uniform vec4 u_ViewInfo; // zfar / znear, zfar +uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height varying vec2 var_ScreenTex; @@ -11,6 +11,7 @@ vec2(0.5784913, -0.002528916), vec2(0.192888, 0.4064181), vec2(-0.6335801, -0.5247476), vec2(-0.5579782, 0.7491854), vec2(0.7320465, 0.6317794) ); +#define NUM_SAMPLES 3 // Input: It uses texture coords as the random number seed. // Output: Random number: [0,1), that is between 0.0 and 0.999999... inclusive. @@ -39,48 +40,47 @@ mat2 randomRotation( const vec2 p ) float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - float sampleZDivW = texture2D(depthMap, tex).r; - return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); + float sampleZDivW = texture2D(depthMap, tex).r; + return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } -float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const float zFar) +float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZNear, const float zFar, const vec2 scale) { float result = 0; - float sampleZ = zFar * getLinearDepth(depthMap, tex, zFarDivZNear); + float sampleZ = getLinearDepth(depthMap, tex, zFarDivZNear); + float scaleZ = zFarDivZNear * sampleZ; - vec2 expectedSlope = vec2(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y)); - - if (length(expectedSlope) > 5000.0) + vec2 slope = vec2(dFdx(sampleZ), dFdy(sampleZ)) / vec2(dFdx(tex.x), dFdy(tex.y)); + + if (length(slope) * zFar > 5000.0) return 1.0; - - vec2 offsetScale = vec2(3.0 / sampleZ); - + + vec2 offsetScale = vec2(scale * 1024.0 / scaleZ); + mat2 rmat = randomRotation(tex); - + + float invZFar = 1.0 / zFar; + float zLimit = 20.0 * invZFar; int i; - for (i = 0; i < 3; i++) + for (i = 0; i < NUM_SAMPLES; i++) { vec2 offset = rmat * poissonDisc[i] * offsetScale; - float sampleZ2 = zFar * getLinearDepth(depthMap, tex + offset, zFarDivZNear); - - if (abs(sampleZ - sampleZ2) > 20.0) - result += 1.0; - else - { - float expectedZ = sampleZ + dot(expectedSlope, offset); - result += step(expectedZ - 1.0, sampleZ2); - } + float sampleDiff = getLinearDepth(depthMap, tex + offset, zFarDivZNear) - sampleZ; + + bool s1 = abs(sampleDiff) > zLimit; + bool s2 = sampleDiff + invZFar > dot(slope, offset); + result += float(s1 || s2); } - - result *= 0.33333; - + + result *= 1.0 / float(NUM_SAMPLES); + return result; } void main() { - float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y); - + float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw); + gl_FragColor = vec4(vec3(result), 1.0); } diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index e0715d04..420c785b 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -1099,8 +1099,8 @@ const void *RB_DrawSurfs( const void *data ) { vec4_t quadVerts[4]; vec2_t texCoords[4]; - viewInfo[2] = 1.0f / (float)(tr.quarterImage[0]->width); - viewInfo[3] = 1.0f / (float)(tr.quarterImage[0]->height); + viewInfo[2] = 1.0f / ((float)(tr.quarterImage[0]->width) * tan(backEnd.viewParms.fovX * M_PI / 360.0f) * 2.0f); + viewInfo[3] = 1.0f / ((float)(tr.quarterImage[0]->height) * tan(backEnd.viewParms.fovY * M_PI / 360.0f) * 2.0f); FBO_Bind(tr.quarterFbo[0]); @@ -1128,6 +1128,9 @@ const void *RB_DrawSurfs( const void *data ) { RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); + viewInfo[2] = 1.0f / (float)(tr.quarterImage[0]->width); + viewInfo[3] = 1.0f / (float)(tr.quarterImage[0]->height); + FBO_Bind(tr.quarterFbo[1]); qglViewport(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); -- cgit From 026f8e89306cc9783c40d75f300c77ab8688cf9b Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Wed, 9 Mar 2016 18:03:23 -0800 Subject: OpenGL2: Create FBOs if target image exists, not cvar settings. --- src/renderergl2/tr_fbo.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index 80d59f62..d013748e 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -310,7 +310,7 @@ void FBO_Init(void) qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); } - if (r_shadowBlur->integer) + if (tr.screenScratchImage) { tr.screenScratchFbo = FBO_Create("screenScratch", tr.screenScratchImage->width, tr.screenScratchImage->height); FBO_AttachImage(tr.screenScratchFbo, tr.screenScratchImage, GL_COLOR_ATTACHMENT0_EXT, 0); @@ -318,7 +318,7 @@ void FBO_Init(void) R_CheckFBO(tr.screenScratchFbo); } - if (r_drawSunRays->integer) + if (tr.sunRaysImage) { tr.sunRaysFbo = FBO_Create("_sunRays", tr.renderDepthImage->width, tr.renderDepthImage->height); FBO_AttachImage(tr.sunRaysFbo, tr.sunRaysImage, GL_COLOR_ATTACHMENT0_EXT, 0); @@ -340,7 +340,7 @@ void FBO_Init(void) if (tr.sunShadowDepthImage[0]) { - for ( i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); // FIXME: this next line wastes 16mb with 4x1024x1024 sun shadow maps, skip if OpenGL 4.3+ or ARB_framebuffer_no_attachments @@ -349,44 +349,58 @@ void FBO_Init(void) FBO_AttachImage(tr.sunShadowFbo[i], tr.sunShadowDepthImage[i], GL_DEPTH_ATTACHMENT_EXT, 0); R_CheckFBO(tr.sunShadowFbo[i]); } + } + if (tr.screenShadowImage) + { tr.screenShadowFbo = FBO_Create("_screenshadow", tr.screenShadowImage->width, tr.screenShadowImage->height); FBO_AttachImage(tr.screenShadowFbo, tr.screenShadowImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.screenShadowFbo); } - for (i = 0; i < 2; i++) + if (tr.textureScratchImage[0]) { - tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); - FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); - R_CheckFBO(tr.textureScratchFbo[i]); + for (i = 0; i < 2; i++) + { + tr.textureScratchFbo[i] = FBO_Create(va("_texturescratch%d", i), tr.textureScratchImage[i]->width, tr.textureScratchImage[i]->height); + FBO_AttachImage(tr.textureScratchFbo[i], tr.textureScratchImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); + R_CheckFBO(tr.textureScratchFbo[i]); + } } + if (tr.calcLevelsImage) { tr.calcLevelsFbo = FBO_Create("_calclevels", tr.calcLevelsImage->width, tr.calcLevelsImage->height); FBO_AttachImage(tr.calcLevelsFbo, tr.calcLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.calcLevelsFbo); } + if (tr.targetLevelsImage) { tr.targetLevelsFbo = FBO_Create("_targetlevels", tr.targetLevelsImage->width, tr.targetLevelsImage->height); FBO_AttachImage(tr.targetLevelsFbo, tr.targetLevelsImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.targetLevelsFbo); } - for (i = 0; i < 2; i++) + if (tr.quarterImage[0]) { - tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); - FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); - R_CheckFBO(tr.quarterFbo[i]); + for (i = 0; i < 2; i++) + { + tr.quarterFbo[i] = FBO_Create(va("_quarter%d", i), tr.quarterImage[i]->width, tr.quarterImage[i]->height); + FBO_AttachImage(tr.quarterFbo[i], tr.quarterImage[i], GL_COLOR_ATTACHMENT0_EXT, 0); + R_CheckFBO(tr.quarterFbo[i]); + } } - if (r_ssao->integer) + if (tr.hdrDepthImage) { tr.hdrDepthFbo = FBO_Create("_hdrDepth", tr.hdrDepthImage->width, tr.hdrDepthImage->height); FBO_AttachImage(tr.hdrDepthFbo, tr.hdrDepthImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.hdrDepthFbo); + } + if (tr.screenSsaoImage) + { tr.screenSsaoFbo = FBO_Create("_screenssao", tr.screenSsaoImage->width, tr.screenSsaoImage->height); FBO_AttachImage(tr.screenSsaoFbo, tr.screenSsaoImage, GL_COLOR_ATTACHMENT0_EXT, 0); R_CheckFBO(tr.screenSsaoFbo); -- cgit From 46cb9a5112fecbdf152bccf692d89bfca564e987 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Thu, 10 Mar 2016 03:44:21 -0800 Subject: OpenGL2: Fixes to depth blur and ssao. --- src/renderergl2/glsl/depthblur_fp.glsl | 11 +++++++---- src/renderergl2/glsl/ssao_fp.glsl | 5 +++-- src/renderergl2/tr_backend.c | 7 ++----- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/renderergl2/glsl/depthblur_fp.glsl b/src/renderergl2/glsl/depthblur_fp.glsl index 60a261c5..a5b264fd 100644 --- a/src/renderergl2/glsl/depthblur_fp.glsl +++ b/src/renderergl2/glsl/depthblur_fp.glsl @@ -4,6 +4,7 @@ uniform sampler2D u_ScreenDepthMap; uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height varying vec2 var_ScreenTex; +//float gauss[8] = float[8](0.17, 0.17, 0.16, 0.14, 0.12, 0.1, 0.08, 0.06); //float gauss[5] = float[5](0.30, 0.23, 0.097, 0.024, 0.0033); float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); //float gauss[3] = float[3](0.60, 0.19, 0.0066); @@ -11,15 +12,17 @@ float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - float sampleZDivW = texture2D(depthMap, tex).r; + // depth is upside down? + float sampleZDivW = texture2D(depthMap, vec2(tex.x, 1.0 - tex.y)).r; return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar, vec2 scale) { float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear); - //scale /= zFarDivZNear * depthCenter; - //int blurSteps = int(float(BLUR_SIZE) / (zFarDivZNear * depthCenter)); + + // enable for less blurring for farther objects + //scale /= min(zFarDivZNear * depthCenter / 32.0, 2.0); #if defined(USE_HORIZONTAL_BLUR) vec2 direction = vec2(scale.x, 0.0); @@ -64,5 +67,5 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa void main() { - gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw); + gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.wz); } diff --git a/src/renderergl2/glsl/ssao_fp.glsl b/src/renderergl2/glsl/ssao_fp.glsl index 84f18cb7..1714c2be 100644 --- a/src/renderergl2/glsl/ssao_fp.glsl +++ b/src/renderergl2/glsl/ssao_fp.glsl @@ -40,7 +40,8 @@ mat2 randomRotation( const vec2 p ) float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - float sampleZDivW = texture2D(depthMap, tex).r; + // depth is upside down? + float sampleZDivW = texture2D(depthMap, vec2(tex.x, 1.0 - tex.y)).r; return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } @@ -80,7 +81,7 @@ float ambientOcclusion(sampler2D depthMap, const vec2 tex, const float zFarDivZN void main() { - float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw); + float result = ambientOcclusion(u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.wz); gl_FragColor = vec4(vec3(result), 1.0); } diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 420c785b..708b395f 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -978,7 +978,7 @@ const void *RB_DrawSurfs( const void *data ) { qglCopyTextureImage2D(tr.renderDepthImage->texnum, GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); } - if (r_ssao->integer) + if (tr.hdrDepthFbo) { // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); @@ -1080,7 +1080,6 @@ const void *RB_DrawSurfs( const void *data ) { RB_InstantQuad2(quadVerts, texCoords); - FBO_Bind(tr.screenShadowFbo); GLSL_BindProgram(&tr.depthBlurShader[1]); @@ -1101,6 +1100,7 @@ const void *RB_DrawSurfs( const void *data ) { viewInfo[2] = 1.0f / ((float)(tr.quarterImage[0]->width) * tan(backEnd.viewParms.fovX * M_PI / 360.0f) * 2.0f); viewInfo[3] = 1.0f / ((float)(tr.quarterImage[0]->height) * tan(backEnd.viewParms.fovY * M_PI / 360.0f) * 2.0f); + viewInfo[3] *= (float)backEnd.viewParms.viewportHeight / (float)backEnd.viewParms.viewportWidth; FBO_Bind(tr.quarterFbo[0]); @@ -1542,9 +1542,6 @@ const void *RB_PostProcess(const void *data) srcBox[3] = backEnd.viewParms.viewportHeight * tr.screenSsaoImage->height / (float)glConfig.vidHeight; //FBO_BlitFromTexture(tr.screenSsaoImage, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); - srcBox[1] = tr.screenSsaoImage->height - srcBox[1]; - srcBox[3] = -srcBox[3]; - FBO_Blit(tr.screenSsaoFbo, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); } -- cgit From e4c921a3b24d7631af8d119a5175321b6eb1c1f7 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Fri, 11 Mar 2016 04:37:50 -0800 Subject: OpenGL2: More ssao/depth blur improvements. --- src/renderergl2/glsl/depthblur_fp.glsl | 18 +++++++++++------- src/renderergl2/glsl/depthblur_vp.glsl | 5 ++++- src/renderergl2/glsl/ssao_fp.glsl | 3 +-- src/renderergl2/tr_backend.c | 7 +++++-- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/renderergl2/glsl/depthblur_fp.glsl b/src/renderergl2/glsl/depthblur_fp.glsl index a5b264fd..9685f6d7 100644 --- a/src/renderergl2/glsl/depthblur_fp.glsl +++ b/src/renderergl2/glsl/depthblur_fp.glsl @@ -9,11 +9,11 @@ varying vec2 var_ScreenTex; float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); //float gauss[3] = float[3](0.60, 0.19, 0.0066); #define BLUR_SIZE 4 +//#define USE_GAUSS float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - // depth is upside down? - float sampleZDivW = texture2D(depthMap, vec2(tex.x, 1.0 - tex.y)).r; + float sampleZDivW = texture2D(depthMap, tex).r; return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } @@ -22,12 +22,14 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear); // enable for less blurring for farther objects - //scale /= min(zFarDivZNear * depthCenter / 32.0, 2.0); + scale /= clamp(zFarDivZNear * depthCenter / 32.0, 1.0, 2.0); #if defined(USE_HORIZONTAL_BLUR) - vec2 direction = vec2(scale.x, 0.0); + vec2 direction = vec2(scale.x * 2.0, 0.0); + vec2 nudge = vec2(0.0, scale.y * 0.5); #else // if defined(USE_VERTICAL_BLUR) - vec2 direction = vec2(0.0, scale.y); + vec2 direction = vec2(0.0, scale.y * 2.0); + vec2 nudge = vec2(scale.x * 0.5, 0.0); #endif vec2 slope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); @@ -46,7 +48,7 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa { for (j = 1; j < BLUR_SIZE; j++) { - vec2 offset = direction * j; + vec2 offset = direction * (float(j) - 0.25) + nudge; float depthSample = getLinearDepth(depthMap, tex + offset, zFarDivZNear); float depthExpected = depthCenter + dot(slope, offset); float useSample = float(abs(depthSample - depthExpected) < zLimit); @@ -57,9 +59,11 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa result += texture2D(imageMap, tex + offset) * useSample; total += useSample; #endif + nudge = -nudge; } direction = -direction; + nudge = -nudge; } return result / total; @@ -67,5 +71,5 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa void main() { - gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.wz); + gl_FragColor = depthGaussian1D(u_ScreenImageMap, u_ScreenDepthMap, var_ScreenTex, u_ViewInfo.x, u_ViewInfo.y, u_ViewInfo.zw); } diff --git a/src/renderergl2/glsl/depthblur_vp.glsl b/src/renderergl2/glsl/depthblur_vp.glsl index 9c46a79f..ba0b6c56 100644 --- a/src/renderergl2/glsl/depthblur_vp.glsl +++ b/src/renderergl2/glsl/depthblur_vp.glsl @@ -1,12 +1,15 @@ attribute vec4 attr_Position; attribute vec4 attr_TexCoord0; +uniform vec4 u_ViewInfo; // zfar / znear, zfar, 1/width, 1/height + varying vec2 var_ScreenTex; void main() { gl_Position = attr_Position; - var_ScreenTex = attr_TexCoord0.xy; + var_ScreenTex = (floor(attr_TexCoord0.xy * (1.0 / u_ViewInfo.zw - vec2(1.0))) + vec2(0.5)) * u_ViewInfo.zw; + //vec2 screenCoords = gl_Position.xy / gl_Position.w; //var_ScreenTex = screenCoords * 0.5 + 0.5; } diff --git a/src/renderergl2/glsl/ssao_fp.glsl b/src/renderergl2/glsl/ssao_fp.glsl index 1714c2be..93f61859 100644 --- a/src/renderergl2/glsl/ssao_fp.glsl +++ b/src/renderergl2/glsl/ssao_fp.glsl @@ -40,8 +40,7 @@ mat2 randomRotation( const vec2 p ) float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { - // depth is upside down? - float sampleZDivW = texture2D(depthMap, vec2(tex.x, 1.0 - tex.y)).r; + float sampleZDivW = texture2D(depthMap, tex).r; return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index 708b395f..f523ab32 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -981,7 +981,11 @@ const void *RB_DrawSurfs( const void *data ) { if (tr.hdrDepthFbo) { // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image - FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); + ivec4_t srcBox; + + VectorSet4(srcBox, 0, tr.renderDepthImage->height, tr.renderDepthImage->width, -tr.renderDepthImage->height); + + FBO_BlitFromTexture(tr.renderDepthImage, srcBox, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); } if (r_sunlightMode->integer && backEnd.viewParms.flags & VPF_USESUNLIGHT) @@ -1541,7 +1545,6 @@ const void *RB_PostProcess(const void *data) srcBox[2] = backEnd.viewParms.viewportWidth * tr.screenSsaoImage->width / (float)glConfig.vidWidth; srcBox[3] = backEnd.viewParms.viewportHeight * tr.screenSsaoImage->height / (float)glConfig.vidHeight; - //FBO_BlitFromTexture(tr.screenSsaoImage, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); FBO_Blit(tr.screenSsaoFbo, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); } -- cgit From beefb51f51ab807f89d67f16488240951bb1af68 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 14 Mar 2016 06:45:51 -0700 Subject: OpenGL2: Fix r_lightmap. --- src/renderergl2/tr_shade.c | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index b8295657..885e2718 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -1142,9 +1142,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) index |= LIGHTDEF_USE_SHADOWMAP; } - if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP) + if (r_lightmap->integer && ((index & LIGHTDEF_LIGHTTYPE_MASK) == LIGHTDEF_USE_LIGHTMAP)) { - index = LIGHTDEF_USE_LIGHTMAP; + index = LIGHTDEF_USE_TCGEN_AND_TCMOD; } sp = &pStage->glslShaderGroup[index]; @@ -1233,19 +1233,32 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } - ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); - GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); + if (r_lightmap->integer) + { + vec4_t v; + VectorSet4(v, 1.0f, 0.0f, 0.0f, 1.0f); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, v); + VectorSet4(v, 0.0f, 0.0f, 0.0f, 0.0f); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, v); - GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); - if (pStage->bundle[0].tcGen == TCGEN_VECTOR) + GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, TCGEN_LIGHTMAP); + } + else { - vec3_t vec; + ComputeTexMods(pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); + GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); - VectorCopy(pStage->bundle[0].tcGenVectors[0], vec); - GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR0, vec); - VectorCopy(pStage->bundle[0].tcGenVectors[1], vec); - GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec); + GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); + if (pStage->bundle[0].tcGen == TCGEN_VECTOR) + { + vec3_t vec; + + VectorCopy(pStage->bundle[0].tcGenVectors[0], vec); + GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR0, vec); + VectorCopy(pStage->bundle[0].tcGenVectors[1], vec); + GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec); + } } GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); @@ -1295,7 +1308,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - if (i == TB_LIGHTMAP) + if (i == TB_COLORMAP) R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i); else GL_BindToTMU( tr.whiteImage, i ); @@ -1305,7 +1318,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { - if (i == TB_LIGHTMAP) + if (i == TB_COLORMAP) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); else GL_BindToTMU( tr.whiteImage, i ); -- cgit From b74cc1c42c5bfb2a0a17fc3c083a5a488c159d0d Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 15 Mar 2016 05:20:25 -0700 Subject: OpenGL2: Fix horribly broken metallic shader. --- src/renderergl2/glsl/lightall_fp.glsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/renderergl2/glsl/lightall_fp.glsl b/src/renderergl2/glsl/lightall_fp.glsl index f16298a3..64cae3fa 100644 --- a/src/renderergl2/glsl/lightall_fp.glsl +++ b/src/renderergl2/glsl/lightall_fp.glsl @@ -333,8 +333,9 @@ void main() // specular red is gloss // specular green is metallicness float gloss = specular.r; - specular.rgb = specular.g * diffuse.rgb + vec3(0.04 - 0.04 * specular.g); - diffuse.rgb *= 1.0 - specular.g; + float metal = specular.g; + specular.rgb = metal * diffuse.rgb + vec3(0.04 - 0.04 * metal); + diffuse.rgb *= 1.0 - metal; #else // diffuse rgb is diffuse // specular rgb is specular reflectance at normal incidence -- cgit From f0a1848858e2681e35753a92e9782851125fc275 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 27 Mar 2016 12:46:38 -0400 Subject: Sys_GetProcessorFeatures() didn't check for 3DNow! or Altivec. --- src/sys/sys_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sys/sys_main.c b/src/sys/sys_main.c index 53084846..2f4b91d7 100644 --- a/src/sys/sys_main.c +++ b/src/sys/sys_main.c @@ -275,10 +275,12 @@ cpuFeatures_t Sys_GetProcessorFeatures( void ) cpuFeatures_t features = 0; #ifndef DEDICATED - if( SDL_HasRDTSC( ) ) features |= CF_RDTSC; - if( SDL_HasMMX( ) ) features |= CF_MMX; - if( SDL_HasSSE( ) ) features |= CF_SSE; - if( SDL_HasSSE2( ) ) features |= CF_SSE2; + if( SDL_HasRDTSC( ) ) features |= CF_RDTSC; + if( SDL_SDL_Has3DNow( ) ) features |= CF_3DNOW; + if( SDL_HasMMX( ) ) features |= CF_MMX; + if( SDL_HasSSE( ) ) features |= CF_SSE; + if( SDL_HasSSE2( ) ) features |= CF_SSE2; + if( SDL_HasAltiVec( ) ) features |= CF_ALTIVEC; #endif return features; -- cgit From a5086e9f0324b9538b853ec90144b6db4877530d Mon Sep 17 00:00:00 2001 From: Zack Middleton Date: Sun, 27 Mar 2016 12:02:12 -0500 Subject: Fix typo of SDL_Has3DNow() in Sys_GetProcessorFeatures() --- src/sys/sys_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sys/sys_main.c b/src/sys/sys_main.c index 2f4b91d7..34367ce4 100644 --- a/src/sys/sys_main.c +++ b/src/sys/sys_main.c @@ -276,7 +276,7 @@ cpuFeatures_t Sys_GetProcessorFeatures( void ) #ifndef DEDICATED if( SDL_HasRDTSC( ) ) features |= CF_RDTSC; - if( SDL_SDL_Has3DNow( ) ) features |= CF_3DNOW; + if( SDL_Has3DNow( ) ) features |= CF_3DNOW; if( SDL_HasMMX( ) ) features |= CF_MMX; if( SDL_HasSSE( ) ) features |= CF_SSE; if( SDL_HasSSE2( ) ) features |= CF_SSE2; -- cgit From 92f4cec8690c90188fed24b0c2b8f0c32d245cbd Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Mon, 28 Mar 2016 22:26:19 -0700 Subject: OpenGL2: Improve cubemap outside error. --- src/renderergl2/tr_main.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/renderergl2/tr_main.c b/src/renderergl2/tr_main.c index f4261033..9751ecb3 100644 --- a/src/renderergl2/tr_main.c +++ b/src/renderergl2/tr_main.c @@ -2932,12 +2932,16 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) { vec3_t ambient, directed, lightDir; + float scale; + R_LightForPoint(tr.refdef.vieworg, ambient, directed, lightDir); - tr.refdef.colorScale = 1.0f; //766.0f / (directed[0] + directed[1] + directed[2] + 1.0f); + scale = directed[0] + directed[1] + directed[2] + ambient[0] + ambient[1] + ambient[2] + 1.0f; + + tr.refdef.colorScale = 1.0f; //766.0f / scale; // only print message for first side - if (directed[0] + directed[1] + directed[2] == 0 && cubemapSide == 0) + if (scale < 1.0001f && cubemapSide == 0) { - ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]); + ri.Printf(PRINT_ALL, "cubemap %d %s (%f, %f, %f) is outside the lightgrid or inside a wall!\n", cubemapIndex, tr.cubemaps[cubemapIndex].name, tr.refdef.vieworg[0], tr.refdef.vieworg[1], tr.refdef.vieworg[2]); } } -- cgit -- cgit From 137f8bc53e9895826548d0f398d6faaa36215bb5 Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 5 Apr 2016 02:21:14 -0700 Subject: OpenGL2: Render metals as nonmetal on cubemaps, and some ComputeShaderColors cleanup. --- src/renderergl2/tr_shade.c | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/renderergl2/tr_shade.c b/src/renderergl2/tr_shade.c index 885e2718..2578420c 100644 --- a/src/renderergl2/tr_shade.c +++ b/src/renderergl2/tr_shade.c @@ -447,11 +447,12 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t || ((blend & GLS_SRCBLEND_BITS) == GLS_SRCBLEND_ONE_MINUS_DST_COLOR) || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_SRC_COLOR) || ((blend & GLS_DSTBLEND_BITS) == GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); + qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL); + float scale = 1.0f; #if defined(USE_OVERBRIGHT) float exactLight = 1.0f; #else - qboolean isWorldDraw = !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL); float exactLight = (isBlend || !isWorldDraw) ? 1.0f : (float)(1 << r_mapOverBrightBits->integer); #endif @@ -611,17 +612,16 @@ static void ComputeShaderColors( shaderStage_t *pStage, vec4_t baseColor, vec4_t break; } - // multiply color by overbrightbits if this isn't a blend if (tr.overbrightBits && !isBlend) + scale *= 1 << tr.overbrightBits; + + if ((backEnd.refdef.colorScale != 1.0f) && !isBlend && isWorldDraw) + scale *= backEnd.refdef.colorScale; + + if (scale != 1.0f) { - float scale = 1 << tr.overbrightBits; - - baseColor[0] *= scale; - baseColor[1] *= scale; - baseColor[2] *= scale; - vertColor[0] *= scale; - vertColor[1] *= scale; - vertColor[2] *= scale; + VectorScale(baseColor, scale, baseColor); + VectorScale(vertColor, scale, vertColor); } // FIXME: find some way to implement this. @@ -1072,6 +1072,8 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) int deformGen; vec5_t deformParams; + qboolean renderToCubemap = tr.renderCubeFbo && glState.currentFBO == tr.renderCubeFbo; + ComputeDeformValues(&deformGen, deformParams); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); @@ -1187,13 +1189,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) ComputeShaderColors(pStage, baseColor, vertColor, pStage->stateBits); - if ((backEnd.refdef.colorScale != 1.0f) && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) - { - // use VectorScale to only scale first three values, not alpha - VectorScale(baseColor, backEnd.refdef.colorScale, baseColor); - VectorScale(vertColor, backEnd.refdef.colorScale, vertColor); - } - GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor); GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor); } @@ -1264,7 +1259,20 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale); - GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); + + { + vec4_t specularScale; + Vector4Copy(pStage->specularScale, specularScale); + + if (renderToCubemap) + { + // force specular to nonmetal if rendering cubemaps + if (r_pbr->integer) + specularScale[1] = 0.0f; + } + + GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); + } //GLSL_SetUniformFloat(sp, UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale); -- cgit From e1c7b8c9bd19f0e4d9b763d1f30c175e49c5397d Mon Sep 17 00:00:00 2001 From: SmileTheory Date: Tue, 5 Apr 2016 02:37:05 -0700 Subject: OpenGL2: Some FBO cleanup, and add non-depth blur to blur shader. --- src/renderergl2/glsl/depthblur_fp.glsl | 17 +++-- src/renderergl2/glsl/depthblur_vp.glsl | 3 +- src/renderergl2/tr_backend.c | 71 ++++++++++++++++++- src/renderergl2/tr_fbo.c | 120 ++++++++++++--------------------- src/renderergl2/tr_fbo.h | 2 +- src/renderergl2/tr_glsl.c | 7 +- src/renderergl2/tr_local.h | 2 +- src/renderergl2/tr_postprocess.c | 51 +++++--------- 8 files changed, 148 insertions(+), 125 deletions(-) diff --git a/src/renderergl2/glsl/depthblur_fp.glsl b/src/renderergl2/glsl/depthblur_fp.glsl index 9685f6d7..d71b3487 100644 --- a/src/renderergl2/glsl/depthblur_fp.glsl +++ b/src/renderergl2/glsl/depthblur_fp.glsl @@ -9,7 +9,10 @@ varying vec2 var_ScreenTex; float gauss[4] = float[4](0.40, 0.24, 0.054, 0.0044); //float gauss[3] = float[3](0.60, 0.19, 0.0066); #define BLUR_SIZE 4 + +#if !defined(USE_DEPTH) //#define USE_GAUSS +#endif float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNear) { @@ -19,21 +22,21 @@ float getLinearDepth(sampler2D depthMap, const vec2 tex, const float zFarDivZNea vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFarDivZNear, float zFar, vec2 scale) { - float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear); - // enable for less blurring for farther objects +#if defined(USE_DEPTH) + float depthCenter = getLinearDepth(depthMap, tex, zFarDivZNear); + vec2 slope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); scale /= clamp(zFarDivZNear * depthCenter / 32.0, 1.0, 2.0); +#endif #if defined(USE_HORIZONTAL_BLUR) vec2 direction = vec2(scale.x * 2.0, 0.0); vec2 nudge = vec2(0.0, scale.y * 0.5); #else // if defined(USE_VERTICAL_BLUR) vec2 direction = vec2(0.0, scale.y * 2.0); - vec2 nudge = vec2(scale.x * 0.5, 0.0); + vec2 nudge = vec2(-scale.x * 0.5, 0.0); #endif - vec2 slope = vec2(dFdx(depthCenter), dFdy(depthCenter)) / vec2(dFdx(tex.x), dFdy(tex.y)); - #if defined(USE_GAUSS) vec4 result = texture2D(imageMap, tex) * gauss[0]; float total = gauss[0]; @@ -49,9 +52,13 @@ vec4 depthGaussian1D(sampler2D imageMap, sampler2D depthMap, vec2 tex, float zFa for (j = 1; j < BLUR_SIZE; j++) { vec2 offset = direction * (float(j) - 0.25) + nudge; +#if defined(USE_DEPTH) float depthSample = getLinearDepth(depthMap, tex + offset, zFarDivZNear); float depthExpected = depthCenter + dot(slope, offset); float useSample = float(abs(depthSample - depthExpected) < zLimit); +#else + float useSample = 1.0; +#endif #if defined(USE_GAUSS) result += texture2D(imageMap, tex + offset) * (gauss[j] * useSample); total += gauss[j] * useSample; diff --git a/src/renderergl2/glsl/depthblur_vp.glsl b/src/renderergl2/glsl/depthblur_vp.glsl index ba0b6c56..9c47660c 100644 --- a/src/renderergl2/glsl/depthblur_vp.glsl +++ b/src/renderergl2/glsl/depthblur_vp.glsl @@ -8,7 +8,8 @@ varying vec2 var_ScreenTex; void main() { gl_Position = attr_Position; - var_ScreenTex = (floor(attr_TexCoord0.xy * (1.0 / u_ViewInfo.zw - vec2(1.0))) + vec2(0.5)) * u_ViewInfo.zw; + vec2 wh = vec2(1.0) / u_ViewInfo.zw - vec2(1.0); + var_ScreenTex = (floor(attr_TexCoord0.xy * wh) + vec2(0.5)) * u_ViewInfo.zw; //vec2 screenCoords = gl_Position.xy / gl_Position.w; //var_ScreenTex = screenCoords * 0.5 + 0.5; diff --git a/src/renderergl2/tr_backend.c b/src/renderergl2/tr_backend.c index f523ab32..0e331752 100644 --- a/src/renderergl2/tr_backend.c +++ b/src/renderergl2/tr_backend.c @@ -981,11 +981,11 @@ const void *RB_DrawSurfs( const void *data ) { if (tr.hdrDepthFbo) { // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image - ivec4_t srcBox; + vec4_t srcTexCoords; - VectorSet4(srcBox, 0, tr.renderDepthImage->height, tr.renderDepthImage->width, -tr.renderDepthImage->height); + VectorSet4(srcTexCoords, 0.0f, 0.0f, 1.0f, 1.0f); - FBO_BlitFromTexture(tr.renderDepthImage, srcBox, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); + FBO_BlitFromTexture(tr.renderDepthImage, srcTexCoords, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); } if (r_sunlightMode->integer && backEnd.viewParms.flags & VPF_USESUNLIGHT) @@ -1585,6 +1585,71 @@ const void *RB_PostProcess(const void *data) else RB_GaussianBlur(backEnd.refdef.blurFactor); +#if 0 + if (0) + { + vec4_t quadVerts[4]; + vec2_t texCoords[4]; + ivec4_t iQtrBox; + vec4_t box; + vec4_t viewInfo; + static float scale = 5.0f; + + scale -= 0.005f; + if (scale < 0.01f) + scale = 5.0f; + + FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + + iQtrBox[0] = backEnd.viewParms.viewportX * tr.quarterImage[0]->width / (float)glConfig.vidWidth; + iQtrBox[1] = backEnd.viewParms.viewportY * tr.quarterImage[0]->height / (float)glConfig.vidHeight; + iQtrBox[2] = backEnd.viewParms.viewportWidth * tr.quarterImage[0]->width / (float)glConfig.vidWidth; + iQtrBox[3] = backEnd.viewParms.viewportHeight * tr.quarterImage[0]->height / (float)glConfig.vidHeight; + + qglViewport(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); + qglScissor(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); + + VectorSet4(box, 0.0f, 0.0f, 1.0f, 1.0f); + + texCoords[0][0] = box[0]; texCoords[0][1] = box[3]; + texCoords[1][0] = box[2]; texCoords[1][1] = box[3]; + texCoords[2][0] = box[2]; texCoords[2][1] = box[1]; + texCoords[3][0] = box[0]; texCoords[3][1] = box[1]; + + VectorSet4(box, -1.0f, -1.0f, 1.0f, 1.0f); + + VectorSet4(quadVerts[0], box[0], box[3], 0, 1); + VectorSet4(quadVerts[1], box[2], box[3], 0, 1); + VectorSet4(quadVerts[2], box[2], box[1], 0, 1); + VectorSet4(quadVerts[3], box[0], box[1], 0, 1); + + GL_State(GLS_DEPTHTEST_DISABLE); + + + VectorSet4(viewInfo, backEnd.viewParms.zFar / r_znear->value, backEnd.viewParms.zFar, 0.0, 0.0); + + viewInfo[2] = scale / (float)(tr.quarterImage[0]->width); + viewInfo[3] = scale / (float)(tr.quarterImage[0]->height); + + FBO_Bind(tr.quarterFbo[1]); + GLSL_BindProgram(&tr.depthBlurShader[2]); + GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); + GLSL_SetUniformVec4(&tr.depthBlurShader[2], UNIFORM_VIEWINFO, viewInfo); + RB_InstantQuad2(quadVerts, texCoords); + + FBO_Bind(tr.quarterFbo[0]); + GLSL_BindProgram(&tr.depthBlurShader[3]); + GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); + GLSL_SetUniformVec4(&tr.depthBlurShader[3], UNIFORM_VIEWINFO, viewInfo); + RB_InstantQuad2(quadVerts, texCoords); + + SetViewportAndScissor(); + + FBO_FastBlit(tr.quarterFbo[1], NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); + FBO_Bind(NULL); + } +#endif + if (0 && r_sunlightMode->integer) { ivec4_t dstBox; diff --git a/src/renderergl2/tr_fbo.c b/src/renderergl2/tr_fbo.c index d013748e..9ba63441 100644 --- a/src/renderergl2/tr_fbo.c +++ b/src/renderergl2/tr_fbo.c @@ -487,10 +487,9 @@ void R_FBOList_f(void) ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs); } -void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) +void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { - ivec4_t dstBox, srcBox; - vec2_t srcTexScale; + ivec4_t dstBox; vec4_t color; vec4_t quadVerts[4]; vec2_t texCoords[4]; @@ -505,49 +504,44 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS return; } - if (inSrcBox) + width = dst ? dst->width : glConfig.vidWidth; + height = dst ? dst->height : glConfig.vidHeight; + + if (inSrcTexCorners) { - VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]); + VectorSet2(texCoords[0], inSrcTexCorners[0], inSrcTexCorners[1]); + VectorSet2(texCoords[1], inSrcTexCorners[2], inSrcTexCorners[1]); + VectorSet2(texCoords[2], inSrcTexCorners[2], inSrcTexCorners[3]); + VectorSet2(texCoords[3], inSrcTexCorners[0], inSrcTexCorners[3]); } else { - VectorSet4(srcBox, 0, 0, src->width, src->height); + VectorSet2(texCoords[0], 0.0f, 1.0f); + VectorSet2(texCoords[1], 1.0f, 1.0f); + VectorSet2(texCoords[2], 1.0f, 0.0f); + VectorSet2(texCoords[3], 0.0f, 0.0f); } // framebuffers are 0 bottom, Y up. if (inDstBox) { - if (dst) - { - dstBox[0] = inDstBox[0]; - dstBox[1] = dst->height - inDstBox[1] - inDstBox[3]; - dstBox[2] = inDstBox[0] + inDstBox[2]; - dstBox[3] = dst->height - inDstBox[1]; - } - else - { - dstBox[0] = inDstBox[0]; - dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3]; - dstBox[2] = inDstBox[0] + inDstBox[2]; - dstBox[3] = glConfig.vidHeight - inDstBox[1]; - } - } - else if (dst) - { - VectorSet4(dstBox, 0, dst->height, dst->width, 0); + dstBox[0] = inDstBox[0]; + dstBox[1] = height - inDstBox[1] - inDstBox[3]; + dstBox[2] = inDstBox[0] + inDstBox[2]; + dstBox[3] = height - inDstBox[1]; } else { - VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0); + VectorSet4(dstBox, 0, height, width, 0); } if (inSrcTexScale) { - VectorCopy2(inSrcTexScale, srcTexScale); + VectorCopy2(inSrcTexScale, invTexRes); } else { - srcTexScale[0] = srcTexScale[1] = 1.0f; + VectorSet2(invTexRes, 1.0f, 1.0f); } if (inColor) @@ -566,17 +560,6 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS FBO_Bind(dst); - if (glState.currentFBO) - { - width = glState.currentFBO->width; - height = glState.currentFBO->height; - } - else - { - width = glConfig.vidWidth; - height = glConfig.vidHeight; - } - qglViewport( 0, 0, width, height ); qglScissor( 0, 0, width, height ); @@ -586,18 +569,13 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS GL_BindToTMU(src, TB_COLORMAP); - VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1); - VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1); - VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1); - VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1); + VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0.0f, 1.0f); + VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0.0f, 1.0f); + VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0.0f, 1.0f); + VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0.0f, 1.0f); - texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height; - texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height; - texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height; - texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height; - - invTexRes[0] = 1.0f / src->width * srcTexScale[0]; - invTexRes[1] = 1.0f / src->height * srcTexScale[1]; + invTexRes[0] /= src->width; + invTexRes[1] /= src->height; GL_State( blend ); @@ -609,14 +587,14 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax); GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); - RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); + RB_InstantQuad2(quadVerts, texCoords); FBO_Bind(oldFbo); } void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend) { - ivec4_t srcBox; + vec4_t srcTexCorners; if (!src) { @@ -624,20 +602,19 @@ void FBO_Blit(FBO_t *src, ivec4_t inSrcBox, vec2_t srcTexScale, FBO_t *dst, ivec return; } - // framebuffers are 0 bottom, Y up. if (inSrcBox) { - srcBox[0] = inSrcBox[0]; - srcBox[1] = src->height - inSrcBox[1] - inSrcBox[3]; - srcBox[2] = inSrcBox[2]; - srcBox[3] = inSrcBox[3]; + srcTexCorners[0] = inSrcBox[0] / (float)src->width; + srcTexCorners[1] = (inSrcBox[1] + inSrcBox[3]) / (float)src->height; + srcTexCorners[2] = (inSrcBox[0] + inSrcBox[2]) / (float)src->width; + srcTexCorners[3] = inSrcBox[1] / (float)src->height; } else { - VectorSet4(srcBox, 0, src->height, src->width, -src->height); + VectorSet4(srcTexCorners, 0.0f, 0.0f, 1.0f, 1.0f); } - FBO_BlitFromTexture(src->colorImage[0], srcBox, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE); + FBO_BlitFromTexture(src->colorImage[0], srcTexCorners, srcTexScale, dst, dstBox, shaderProgram, color, blend | GLS_DEPTHTEST_DISABLE); } void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter) @@ -651,22 +628,15 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu return; } - // get to a neutral state first - //FBO_Bind(NULL); - srcFb = src ? src->frameBuffer : 0; dstFb = dst ? dst->frameBuffer : 0; if (!srcBox) { - if (src) - { - VectorSet4(srcBoxFinal, 0, 0, src->width, src->height); - } - else - { - VectorSet4(srcBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight); - } + int width = src ? src->width : glConfig.vidWidth; + int height = src ? src->height : glConfig.vidHeight; + + VectorSet4(srcBoxFinal, 0, 0, width, height); } else { @@ -675,14 +645,10 @@ void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int bu if (!dstBox) { - if (dst) - { - VectorSet4(dstBoxFinal, 0, 0, dst->width, dst->height); - } - else - { - VectorSet4(dstBoxFinal, 0, 0, glConfig.vidWidth, glConfig.vidHeight); - } + int width = dst ? dst->width : glConfig.vidWidth; + int height = dst ? dst->height : glConfig.vidHeight; + + VectorSet4(dstBoxFinal, 0, 0, width, height); } else { diff --git a/src/renderergl2/tr_fbo.h b/src/renderergl2/tr_fbo.h index 72b2c911..cb14af6b 100644 --- a/src/renderergl2/tr_fbo.h +++ b/src/renderergl2/tr_fbo.h @@ -57,7 +57,7 @@ void FBO_Bind(FBO_t *fbo); void FBO_Init(void); void FBO_Shutdown(void); -void FBO_BlitFromTexture(struct image_s *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend); +void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend); void FBO_Blit(FBO_t *src, ivec4_t srcBox, vec2_t srcTexScale, FBO_t *dst, ivec4_t dstBox, struct shaderProgram_s *shaderProgram, vec4_t color, int blend); void FBO_FastBlit(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, int buffers, int filter); diff --git a/src/renderergl2/tr_glsl.c b/src/renderergl2/tr_glsl.c index b825c19e..683e173d 100644 --- a/src/renderergl2/tr_glsl.c +++ b/src/renderergl2/tr_glsl.c @@ -1284,7 +1284,7 @@ void GLSL_InitGPUShaders(void) numEtcShaders++; - for (i = 0; i < 2; i++) + for (i = 0; i < 4; i++) { attribs = ATTR_POSITION | ATTR_TEXCOORD; extradefines[0] = '\0'; @@ -1294,6 +1294,9 @@ void GLSL_InitGPUShaders(void) else Q_strcat(extradefines, 1024, "#define USE_HORIZONTAL_BLUR\n"); + if (!(i & 2)) + Q_strcat(extradefines, 1024, "#define USE_DEPTH\n"); + if (!GLSL_InitGPUShader(&tr.depthBlurShader[i], "depthBlur", attribs, qtrue, extradefines, qtrue, fallbackShader_depthblur_vp, fallbackShader_depthblur_fp)) { @@ -1373,7 +1376,7 @@ void GLSL_ShutdownGPUShaders(void) GLSL_DeleteGPUShader(&tr.shadowmaskShader); GLSL_DeleteGPUShader(&tr.ssaoShader); - for ( i = 0; i < 2; i++) + for ( i = 0; i < 4; i++) GLSL_DeleteGPUShader(&tr.depthBlurShader[i]); } diff --git a/src/renderergl2/tr_local.h b/src/renderergl2/tr_local.h index d11c4870..5af67a13 100644 --- a/src/renderergl2/tr_local.h +++ b/src/renderergl2/tr_local.h @@ -1592,7 +1592,7 @@ typedef struct { shaderProgram_t calclevels4xShader[2]; shaderProgram_t shadowmaskShader; shaderProgram_t ssaoShader; - shaderProgram_t depthBlurShader[2]; + shaderProgram_t depthBlurShader[4]; shaderProgram_t testcubeShader; diff --git a/src/renderergl2/tr_postprocess.c b/src/renderergl2/tr_postprocess.c index 1952ae96..c4e51554 100644 --- a/src/renderergl2/tr_postprocess.c +++ b/src/renderergl2/tr_postprocess.c @@ -227,6 +227,7 @@ void RB_BokehBlur(FBO_t *src, ivec4_t srcBox, FBO_t *dst, ivec4_t dstBox, float static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretch, float x, float y, float w, float h, float xcenter, float ycenter, float alpha) { ivec4_t srcBox, dstBox; + int srcWidth, srcHeight; vec4_t color; const float inc = 1.f / passes; const float mul = powf(stretch, inc); @@ -235,10 +236,10 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretc alpha *= inc; VectorSet4(color, alpha, alpha, alpha, 1.0f); - if (srcFbo) - VectorSet4(srcBox, 0, 0, srcFbo->width, srcFbo->height); - else - VectorSet4(srcBox, 0, 0, glConfig.vidWidth, glConfig.vidHeight); + srcWidth = srcFbo ? srcFbo->width : glConfig.vidWidth; + srcHeight = srcFbo ? srcFbo->height : glConfig.vidHeight; + + VectorSet4(srcBox, 0, 0, srcWidth, srcHeight); VectorSet4(dstBox, x, y, w, h); FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, 0); @@ -251,20 +252,10 @@ static void RB_RadialBlur(FBO_t *srcFbo, FBO_t *dstFbo, int passes, float stretc float s0 = xcenter * (1.f - iscale); float t0 = (1.0f - ycenter) * (1.f - iscale); - if (srcFbo) - { - srcBox[0] = s0 * srcFbo->width; - srcBox[1] = t0 * srcFbo->height; - srcBox[2] = iscale * srcFbo->width; - srcBox[3] = iscale * srcFbo->height; - } - else - { - srcBox[0] = s0 * glConfig.vidWidth; - srcBox[1] = t0 * glConfig.vidHeight; - srcBox[2] = iscale * glConfig.vidWidth; - srcBox[3] = iscale * glConfig.vidHeight; - } + srcBox[0] = s0 * srcWidth; + srcBox[1] = t0 * srcHeight; + srcBox[2] = iscale * srcWidth; + srcBox[3] = iscale * srcHeight; FBO_Blit(srcFbo, srcBox, NULL, dstFbo, dstBox, NULL, color, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); @@ -349,23 +340,15 @@ void RB_SunRays(FBO_t *srcFbo, ivec4_t srcBox, FBO_t *dstFbo, ivec4_t dstBox) { float mul = 1.f; ivec4_t rayBox, quarterBox; + int srcWidth = srcFbo ? srcFbo->width : glConfig.vidWidth; + int srcHeight = srcFbo ? srcFbo->height : glConfig.vidHeight; VectorSet4(color, mul, mul, mul, 1); - if (srcFbo) - { - rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / srcFbo->width; - rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / srcFbo->height; - rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / srcFbo->width; - rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / srcFbo->height; - } - else - { - rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / glConfig.vidWidth; - rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / glConfig.vidHeight; - rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / glConfig.vidWidth; - rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / glConfig.vidHeight; - } + rayBox[0] = srcBox[0] * tr.sunRaysFbo->width / srcWidth; + rayBox[1] = srcBox[1] * tr.sunRaysFbo->height / srcHeight; + rayBox[2] = srcBox[2] * tr.sunRaysFbo->width / srcWidth; + rayBox[3] = srcBox[3] * tr.sunRaysFbo->height / srcHeight; quarterBox[0] = 0; quarterBox[1] = tr.quarterFbo[0]->height; @@ -483,10 +466,8 @@ void RB_GaussianBlur(float blur) FBO_FastBlit(tr.quarterFbo[0], NULL, tr.textureScratchFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); // set the alpha channel - VectorSet4(srcBox, 0, 0, tr.whiteImage->width, tr.whiteImage->height); - VectorSet4(dstBox, 0, 0, tr.textureScratchFbo[0]->width, tr.textureScratchFbo[0]->height); qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - FBO_BlitFromTexture(tr.whiteImage, srcBox, NULL, tr.textureScratchFbo[0], dstBox, NULL, color, GLS_DEPTHTEST_DISABLE); + FBO_BlitFromTexture(tr.whiteImage, NULL, NULL, tr.textureScratchFbo[0], NULL, NULL, color, GLS_DEPTHTEST_DISABLE); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // blur the tiny buffer horizontally and vertically -- cgit From 5658bc638f194fd6be9593860b6faf16baea8190 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Thu, 7 Apr 2016 11:54:15 +0100 Subject: Merged ioq3 1f6703821f11be9c711c6ee42371ab290dd12776 --- misc/last-merged-ioq3-revision | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/last-merged-ioq3-revision b/misc/last-merged-ioq3-revision index cc9c1499..4cdf56c4 100644 --- a/misc/last-merged-ioq3-revision +++ b/misc/last-merged-ioq3-revision @@ -1 +1 @@ -708fe6937a7bf4a838766d1c3a07552160ab4f1e +1f6703821f11be9c711c6ee42371ab290dd12776 -- cgit From 87abdd914988724e164ffb16380ad26be8420b84 Mon Sep 17 00:00:00 2001 From: Tim Angus Date: Thu, 7 Apr 2016 11:58:19 +0100 Subject: Make it compile --- src/qcommon/files.c | 23 +--------------- src/renderergl2/tr_image.c | 2 +- src/server/sv_ccmds.c | 65 ---------------------------------------------- 3 files changed, 2 insertions(+), 88 deletions(-) diff --git a/src/qcommon/files.c b/src/qcommon/files.c index 02235bcf..8e1cd0d3 100644 --- a/src/qcommon/files.c +++ b/src/qcommon/files.c @@ -2448,8 +2448,6 @@ int FS_GetModList( char *listbuf, int bufsize ) { int dummy; char **pFiles0 = NULL; char **pFiles1 = NULL; - char **pFiles2 = NULL; - char **pFiles3 = NULL; qboolean bDrop = qfalse; *listbuf = 0; @@ -2457,11 +2455,7 @@ int FS_GetModList( char *listbuf, int bufsize ) { pFiles0 = Sys_ListFiles( fs_homepath->string, NULL, NULL, &dummy, qtrue ); pFiles1 = Sys_ListFiles( fs_basepath->string, NULL, NULL, &dummy, qtrue ); - pFiles2 = Sys_ListFiles( fs_steampath->string, NULL, NULL, &dummy, qtrue ); - // we searched for mods in the three paths - // it is likely that we have duplicate names now, which we will cleanup below - pFiles3 = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); - pFiles = Sys_ConcatenateFileLists( pFiles2, pFiles3 ); + pFiles = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); nPotential = Sys_CountFileList(pFiles); @@ -2504,15 +2498,6 @@ int FS_GetModList( char *listbuf, int bufsize ) { Sys_FreeFileList( pPaks ); } - /* try on steam path */ - if ( nPaks <= 0 ) - { - path = FS_BuildOSPath( fs_steampath->string, name, "" ); - nPaks = 0; - pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse ); - Sys_FreeFileList( pPaks ); - } - if (nPaks > 0) { nLen = strlen(name) + 1; // nLen is the length of the mod path @@ -3241,9 +3226,6 @@ static void FS_Startup( const char *gameName ) // check for additional base game so mods can be based upon other mods if ( fs_basegame->string[0] && Q_stricmp( fs_basegame->string, gameName ) ) { - if (fs_steampath->string[0]) { - FS_AddGameDirectory(fs_steampath->string, fs_basegame->string); - } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_basegame->string); } @@ -3254,9 +3236,6 @@ static void FS_Startup( const char *gameName ) // check for additional game folder for mods if ( fs_gamedirvar->string[0] && Q_stricmp( fs_gamedirvar->string, gameName ) ) { - if (fs_steampath->string[0]) { - FS_AddGameDirectory(fs_steampath->string, fs_gamedirvar->string); - } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string); } diff --git a/src/renderergl2/tr_image.c b/src/renderergl2/tr_image.c index 7e2d452e..331e7f61 100644 --- a/src/renderergl2/tr_image.c +++ b/src/renderergl2/tr_image.c @@ -2114,7 +2114,7 @@ done: { if (glConfig.textureFilterAnisotropic && !cubemap) qglTextureParameteri(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, - (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer)); + (GLint)Com_Clamp(1, glConfig.maxAnisotropy, r_ext_max_anisotropy->integer)); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max); diff --git a/src/server/sv_ccmds.c b/src/server/sv_ccmds.c index 1cc6cf3e..3ec3b8c7 100644 --- a/src/server/sv_ccmds.c +++ b/src/server/sv_ccmds.c @@ -223,71 +223,6 @@ static void SV_MapRestart_f( void ) { } -/* -================== -SV_ConSayto_f -================== -*/ -static void SV_ConSayto_f(void) { - char *p; - char text[1024]; - client_t *cl; - char *rawname; - char name[MAX_NAME_LENGTH]; - char cleanName[MAX_NAME_LENGTH]; - client_t *saytocl; - int i; - - // make sure server is running - if ( !com_sv_running->integer ) { - Com_Printf( "Server is not running.\n" ); - return; - } - - if ( Cmd_Argc() < 3 ) { - Com_Printf ("Usage: sayto \n"); - return; - } - - rawname = Cmd_Argv(1); - - //allowing special characters in the console - //with hex strings for player names - Com_FieldStringToPlayerName( name, MAX_NAME_LENGTH, rawname ); - - saytocl = NULL; - for ( i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++ ) { - if ( !cl->state ) { - continue; - } - Q_strncpyz( cleanName, cl->name, sizeof(cleanName) ); - Q_CleanStr( cleanName ); - - if ( !Q_stricmp( cleanName, name ) ) { - saytocl = cl; - break; - } - } - if( !saytocl ) - { - Com_Printf ("No such player name: %s.\n", name); - return; - } - - strcpy (text, "console_sayto: "); - p = Cmd_ArgsFrom(2); - - if ( *p == '"' ) { - p++; - p[strlen(p)-1] = 0; - } - - strcat(text, p); - - SV_SendServerCommand(saytocl, "chat \"%s\"", text); -} - - /* ================== SV_Heartbeat_f -- cgit