diff --git a/src/client/cl_main.c b/src/client/cl_main.c index 2e68f14f..e1082d7d 100644 --- a/src/client/cl_main.c +++ b/src/client/cl_main.c @@ -595,6 +595,7 @@ void CL_PlayDemo_f( void ) { Con_Close(); cls.state = CA_CONNECTED; + clientIsConnected = qtrue; clc.demoplaying = qtrue; if ( Cvar_VariableValue( "cl_wavefilerecord" ) ) { @@ -734,6 +735,7 @@ void CL_MapLoading( void ) { // if we are already connected to the local host, stay connected if ( cls.state >= CA_CONNECTED && !Q_stricmp( cls.servername, "localhost" ) ) { cls.state = CA_CONNECTED; // so the connect screen is drawn + clientIsConnected = qtrue; memset( cls.updateInfoString, 0, sizeof( cls.updateInfoString ) ); memset( clc.serverMessage, 0, sizeof( clc.serverMessage ) ); memset( &cl.gameState, 0, sizeof( cl.gameState ) ); @@ -821,6 +823,7 @@ void CL_Disconnect( qboolean showMainMenu ) { CL_WritePacket(); CL_WritePacket(); CL_WritePacket(); + clientIsConnected = qfalse; } CL_ClearState(); @@ -828,15 +831,31 @@ void CL_Disconnect( qboolean showMainMenu ) { // wipe the client connection memset( &clc, 0, sizeof( clc ) ); - cls.state = CA_DISCONNECTED; +// L0 - Fix shutdowns .. + if (uivm && cls.state > CA_DISCONNECTED) { + cls.state = CA_DISCONNECTED; + clientIsConnected = qfalse; + + // shutdown the UI + CL_ShutdownUI(); + + // init the UI + CL_InitUI(); + } + else { + cls.state = CA_DISCONNECTED; + clientIsConnected = qfalse; + } // allow cheats locally Cvar_Set( "sv_cheats", "1" ); // not connected to a pure server anymore cl_connectedToPureServer = qfalse; -} + // L0 - Set this to off as well + clientIsConnected = qfalse; +} /* =================== @@ -1588,6 +1607,7 @@ void CL_InitDownloads( void ) { Q_strncpyz( autoupdateFilename, cl_updatefiles->string, sizeof( autoupdateFilename ) ); Q_strncpyz( clc.downloadList, va( "@%s/%s@%s/%s", dir, cl_updatefiles->string, dir, cl_updatefiles->string ), MAX_INFO_STRING ); cls.state = CA_CONNECTED; + clientIsConnected = qtrue; CL_NextDownload(); return; } @@ -1607,6 +1627,7 @@ void CL_InitDownloads( void ) { if ( *clc.downloadList ) { // if autodownloading is not enabled on the server cls.state = CA_CONNECTED; + clientIsConnected = qtrue; CL_NextDownload(); return; } @@ -2006,6 +2027,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { Netchan_Setup( NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); cls.state = CA_CONNECTED; clc.lastPacketSentTime = -9999; // send first packet immediately + clientIsConnected = qfalse; return; } @@ -2199,6 +2221,7 @@ void CL_Frame( int msec ) { // if disconnected, bring up the menu S_StopAllSounds(); VM_Call( uivm, UI_SET_ACTIVE_MENU, UIMENU_MAIN ); + clientIsConnected = qfalse; } // if recording an avi, lock to a fixed fps @@ -2604,6 +2627,7 @@ void CL_GetAutoUpdate( void ) { if ( cls.autoupdateServer.type == NA_BAD ) { Com_Printf( "Bad server address\n" ); cls.state = CA_DISCONNECTED; + clientIsConnected = qfalse; return; } diff --git a/src/client/cl_scrn.c b/src/client/cl_scrn.c index 655f34d7..2b695a81 100644 --- a/src/client/cl_scrn.c +++ b/src/client/cl_scrn.c @@ -474,6 +474,7 @@ void SCR_DrawScreenField( stereoFrame_t stereoFrame ) { case CA_CONNECTING: case CA_CHALLENGING: case CA_CONNECTED: + clientIsConnected = qtrue; // L0 - Set this on.. // connecting clients will only show the connection dialog // refresh to update the time VM_Call( uivm, UI_REFRESH, cls.realtime ); diff --git a/src/game/game.vcxproj b/src/game/game.vcxproj index 8d11e66e..d05fc668 100644 --- a/src/game/game.vcxproj +++ b/src/game/game.vcxproj @@ -311,7 +311,6 @@ copy $(SolutionDir)Builds\$(Configuration)\$(ProjectName)\$(TargetName)$(TargetE - diff --git a/src/game/game.vcxproj.filters b/src/game/game.vcxproj.filters index b7e799f4..e64909b1 100644 --- a/src/game/game.vcxproj.filters +++ b/src/game/game.vcxproj.filters @@ -187,9 +187,6 @@ Source Files - - Source Files - Source Files diff --git a/src/game/q_shared.h b/src/game/q_shared.h index d66df38c..d320cc37 100644 --- a/src/game/q_shared.h +++ b/src/game/q_shared.h @@ -962,19 +962,18 @@ COLLISION DETECTION // plane types are used to speed some tests // 0-2 are axial planes -#define PLANE_X 0 -#define PLANE_Y 1 -#define PLANE_Z 2 -#define PLANE_NON_AXIAL 3 - +#define PLANE_X 0 +#define PLANE_Y 1 +#define PLANE_Z 2 +#define PLANE_NON_AXIAL 3 +#define PLANE_NON_PLANAR 4 /* ================= PlaneTypeForNormal ================= */ - -#define PlaneTypeForNormal( x ) ( x[0] == 1.0 ? PLANE_X : ( x[1] == 1.0 ? PLANE_Y : ( x[2] == 1.0 ? PLANE_Z : PLANE_NON_AXIAL ) ) ) +#define PlaneTypeForNormal( x ) ( x[0] == 1.0 ? PLANE_X : ( x[1] == 1.0 ? PLANE_Y : ( x[2] == 1.0 ? PLANE_Z : ( x[0] == 0.f && x[1] == 0.f && x[2] == 0.f ? PLANE_NON_PLANAR : PLANE_NON_AXIAL ) ) ) ) // plane_t structure // !!! if this is changed, it must be changed in asm code too !!! @@ -1539,6 +1538,11 @@ typedef enum { CA_CINEMATIC // playing a cinematic or a static pic, not connected to a server } connstate_t; +// L0 +// Indicates if client is connected or not. +// Deals with Bloom issues as well as just identifying if extra stuff should be ran.. +qboolean clientIsConnected; + // font support #define GLYPH_START 0 diff --git a/src/qcommon/qfiles.h b/src/qcommon/qfiles.h index 11297a4a..3e24fa67 100644 --- a/src/qcommon/qfiles.h +++ b/src/qcommon/qfiles.h @@ -692,12 +692,15 @@ typedef struct { byte color[4]; } drawVert_t; +#define drawVert_t_cleared(x) drawVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0, 0}} + typedef enum { MST_BAD, MST_PLANAR, MST_PATCH, MST_TRIANGLE_SOUP, - MST_FLARE + MST_FLARE, + MST_FOLIAGE // L0 - TODO: add support for foliage surfaces } mapSurfaceType_t; typedef struct { diff --git a/src/renderer/renderer.vcxproj b/src/renderer/renderer.vcxproj index 5e891b27..82206e8a 100644 --- a/src/renderer/renderer.vcxproj +++ b/src/renderer/renderer.vcxproj @@ -351,6 +351,7 @@ true MaxSpeed + Disabled EnableFastChecks diff --git a/src/renderer/renderer.vcxproj.filters b/src/renderer/renderer.vcxproj.filters index a167dd17..928cd301 100644 --- a/src/renderer/renderer.vcxproj.filters +++ b/src/renderer/renderer.vcxproj.filters @@ -190,6 +190,9 @@ Source Files + + Source Files + diff --git a/src/renderer/tr_backend.c b/src/renderer/tr_backend.c index 37b06efd..98c241f7 100644 --- a/src/renderer/tr_backend.c +++ b/src/renderer/tr_backend.c @@ -483,6 +483,10 @@ void RB_BeginDrawingView( void ) { qglClearColor( glfogsettings[FOG_CURRENT].color[0], glfogsettings[FOG_CURRENT].color[1], glfogsettings[FOG_CURRENT].color[2], glfogsettings[FOG_CURRENT].color[3] ); } + else if (!(r_portalsky->integer)) { // ydnar: portal skies have been manually turned off, clear bg color + clearBits |= GL_COLOR_BUFFER_BIT; + qglClearColor(0.5, 0.5, 0.5, 1.0); + } } } else { // world scene with no portal sky clearBits |= GL_DEPTH_BUFFER_BIT; @@ -513,6 +517,10 @@ void RB_BeginDrawingView( void ) { } } + // ydnar: don't clear the color buffer when no world model is specified + if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) { + clearBits &= ~GL_COLOR_BUFFER_BIT; + } if ( clearBits ) { qglClear( clearBits ); @@ -1140,6 +1148,7 @@ const void *RB_DrawSurfs( const void *data ) { backEnd.refdef = cmd->refdef; backEnd.viewParms = cmd->viewParms; + backEnd.doneSurfaces = qtrue; RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); @@ -1281,6 +1290,8 @@ const void *RB_SwapBuffers( const void *data ) { GLimp_EndFrame(); backEnd.projection2D = qfalse; + backEnd.doneBloom = qfalse; + backEnd.doneSurfaces = qfalse; return (const void *)( cmd + 1 ); } @@ -1310,6 +1321,7 @@ void RB_ExecuteRenderCommands( const void *data ) { data = RB_SetColor( data ); break; case RC_STRETCH_PIC: + R_BloomScreen(); data = RB_StretchPic( data ); break; case RC_ROTATED_PIC: @@ -1325,6 +1337,7 @@ void RB_ExecuteRenderCommands( const void *data ) { data = RB_DrawBuffer( data ); break; case RC_SWAP_BUFFERS: + R_BloomScreen(); data = RB_SwapBuffers( data ); break; diff --git a/src/renderer/tr_bloom.c b/src/renderer/tr_bloom.c new file mode 100644 index 00000000..c6890a8a --- /dev/null +++ b/src/renderer/tr_bloom.c @@ -0,0 +1,371 @@ +/* +Copyright (C) 1997-2001 Id Software, Inc. + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// tr_bloom.c: 2D lighting post process effect + +#include "tr_local.h" + +static cvar_t *r_bloom; +static cvar_t *r_bloom_sample_size; +static cvar_t *r_bloom_fast_sample; +static cvar_t *r_bloom_alpha; +static cvar_t *r_bloom_darken; +static cvar_t *r_bloom_intensity; +static cvar_t *r_bloom_diamond_size; + +/* +============================================================================== + +LIGHT BLOOMS + +============================================================================== +*/ + +static float Diamond8x[8][8] = +{ + { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f, }, + { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, }, + { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, }, + { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, }, + { 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, }, + { 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, }, + { 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, }, + { 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f } +}; + +static float Diamond6x[6][6] = +{ + { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, }, + { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, }, + { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, }, + { 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, }, + { 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, }, + { 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f } +}; + +static float Diamond4x[4][4] = +{ + { 0.3f, 0.4f, 0.4f, 0.3f, }, + { 0.4f, 0.9f, 0.9f, 0.4f, }, + { 0.4f, 0.9f, 0.9f, 0.4f, }, + { 0.3f, 0.4f, 0.4f, 0.3f } +}; + +static struct { + struct { + image_t *texture; + int width, height; + float readW, readH; + } effect; + struct { + image_t *texture; + int width, height; + float readW, readH; + } screen; + struct { + int width, height; + } work; + qboolean started; +} bloom; + +static void ID_INLINE R_Bloom_Quad(int width, int height, float texX, float texY, float texWidth, float texHeight) { + int x = 0; + int y = 0; + x = 0; + y += glConfig.vidHeight - height; + width += x; + height += y; + + texWidth += texX; + texHeight += texY; + + qglBegin(GL_QUADS); + qglTexCoord2f(texX, texHeight); + qglVertex2f(x, y); + + qglTexCoord2f(texX, texY); + qglVertex2f(x, height); + + qglTexCoord2f(texWidth, texY); + qglVertex2f(width, height); + + qglTexCoord2f(texWidth, texHeight); + qglVertex2f(width, y); + qglEnd(); +} + + +/* +================= +R_Bloom_InitTextures +================= +*/ +static void R_Bloom_InitTextures(void) +{ + byte *data; + + // find closer power of 2 to screen size + for (bloom.screen.width = 1; bloom.screen.width< glConfig.vidWidth; bloom.screen.width *= 2); + for (bloom.screen.height = 1; bloom.screen.height < glConfig.vidHeight; bloom.screen.height *= 2); + + bloom.screen.readW = glConfig.vidWidth / (float)bloom.screen.width; + bloom.screen.readH = glConfig.vidHeight / (float)bloom.screen.height; + + // find closer power of 2 to effect size + bloom.work.width = r_bloom_sample_size->integer; + bloom.work.height = bloom.work.width * (glConfig.vidWidth / glConfig.vidHeight); + + for (bloom.effect.width = 1; bloom.effect.width < bloom.work.width; bloom.effect.width *= 2); + for (bloom.effect.height = 1; bloom.effect.height < bloom.work.height; bloom.effect.height *= 2); + + bloom.effect.readW = bloom.work.width / (float)bloom.effect.width; + bloom.effect.readH = bloom.work.height / (float)bloom.effect.height; + + + // disable blooms if we can't handle a texture of that size + if (bloom.screen.width > glConfig.maxTextureSize || + bloom.screen.height > glConfig.maxTextureSize || + bloom.effect.width > glConfig.maxTextureSize || + bloom.effect.height > glConfig.maxTextureSize || + bloom.work.width > glConfig.vidWidth || + bloom.work.height > glConfig.vidHeight + ) { + ri.Cvar_Set("r_bloom", "0"); + Com_Printf(S_COLOR_YELLOW"WARNING: 'R_InitBloomTextures' too high resolution for light bloom, effect disabled\n"); + return; + } + + data = ri.Hunk_AllocateTempMemory(bloom.screen.width * bloom.screen.height * 4); + Com_Memset(data, 0, bloom.screen.width * bloom.screen.height * 4); + bloom.screen.texture = R_CreateImage("***bloom screen texture***", data, bloom.screen.width, bloom.screen.height, qfalse, qfalse, qfalse); + ri.Hunk_FreeTempMemory(data); + + data = ri.Hunk_AllocateTempMemory(bloom.effect.width * bloom.effect.height * 4); + Com_Memset(data, 0, bloom.effect.width * bloom.effect.height * 4); + bloom.effect.texture = R_CreateImage("***bloom effect texture***", data, bloom.effect.width, bloom.effect.height, qfalse, qfalse, qfalse); + ri.Hunk_FreeTempMemory(data); + bloom.started = qtrue; +} + +/* +================= +R_InitBloomTextures +================= +*/ +void R_InitBloomTextures(void) +{ + if (!r_bloom->integer) + return; + if (r_rmse->integer) // this breaks bloom + return; + memset(&bloom, 0, sizeof(bloom)); + R_Bloom_InitTextures(); +} + +/* +================= +R_Bloom_DrawEffect +================= +*/ +static void R_Bloom_DrawEffect(void) +{ + GL_Bind(bloom.effect.texture); + GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); + qglColor4f(r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f); + R_Bloom_Quad(glConfig.vidWidth, glConfig.vidHeight, 0, 0, bloom.effect.readW, bloom.effect.readW); +} + + +/* +================= +R_Bloom_GeneratexDiamonds +================= +*/ +static void R_Bloom_WarsowEffect(void) { + int i, j, k; + float intensity, scale, *diamond; + + qglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + //Take the backup texture and downscale it + GL_Bind(bloom.screen.texture); + GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO); + R_Bloom_Quad(bloom.work.width, bloom.work.height, 0, 0, bloom.screen.readW, bloom.screen.readH); + //Copy downscaled framebuffer into a texture + GL_Bind(bloom.effect.texture); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height); + // darkening passes with repeated filter + if (r_bloom_darken->integer) { + int i; + GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); + + for (i = 0; i < r_bloom_darken->integer; i++) { + R_Bloom_Quad(bloom.work.width, bloom.work.height, + 0, 0, + bloom.effect.readW, bloom.effect.readH); + } + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height); + } + /* Copy the result to the effect texture */ + GL_Bind(bloom.effect.texture); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height); + + // bluring passes, warsow uses a repeated semi blend on a selectable diamond grid + qglColor4f(1.0f, 1.0f, 1.0f, 1.0f); + GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); + if (r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3) { + if (r_bloom_diamond_size->integer != 8) + ri.Cvar_Set("r_bloom_diamond_size", "8"); + } + else if (r_bloom_diamond_size->integer > 5) { + if (r_bloom_diamond_size->integer != 6) + ri.Cvar_Set("r_bloom_diamond_size", "6"); + } + else if (r_bloom_diamond_size->integer > 3) { + if (r_bloom_diamond_size->integer != 4) + ri.Cvar_Set("r_bloom_diamond_size", "4"); + } + + switch (r_bloom_diamond_size->integer) { + case 4: + k = 2; + diamond = &Diamond4x[0][0]; + scale = r_bloom_intensity->value * 0.8f; + break; + case 6: + k = 3; + diamond = &Diamond6x[0][0]; + scale = r_bloom_intensity->value * 0.5f; + break; + default: + // case 8: + k = 4; + diamond = &Diamond8x[0][0]; + scale = r_bloom_intensity->value * 0.3f; + break; + } + + for (i = 0; i < r_bloom_diamond_size->integer; i++) { + for (j = 0; j < r_bloom_diamond_size->integer; j++, diamond++) { + float x, y; + intensity = *diamond * scale; + if (intensity < 0.01f) + continue; + qglColor4f(intensity, intensity, intensity, 1.0); + x = (i - k) * (2 / 640.0f) * bloom.effect.readW; + y = (j - k) * (2 / 480.0f) * bloom.effect.readH; + + R_Bloom_Quad(bloom.work.width, bloom.work.height, x, y, bloom.effect.readW, bloom.effect.readH); + } + } + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, bloom.work.width, bloom.work.height); +} + +/* +================= +R_Bloom_BackupScreen +Backup the full original screen to a texture for downscaling and later restoration +================= +*/ +static void R_Bloom_BackupScreen(void) { + GL_Bind(bloom.screen.texture); + qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight); +} +/* +================= +R_Bloom_RestoreScreen +Restore the temporary framebuffer section we used with the backup texture +================= +*/ +static void R_Bloom_RestoreScreen(void) { + GL_State(GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO); + GL_Bind(bloom.screen.texture); + qglColor4f(1, 1, 1, 1); + R_Bloom_Quad(bloom.work.width, bloom.work.height, 0, 0, + bloom.work.width / (float)bloom.screen.width, + bloom.work.height / (float)bloom.screen.height); +} + +/* +================= +R_BloomScreen +================= +*/ +void R_BloomScreen(void) +{ + if (!r_bloom->integer) + return; + if (r_rmse->integer) { // this breaks bloom + ri.Cvar_Set("r_bloom", "0"); + Com_Printf(S_COLOR_YELLOW "WARNING: 'r_rmse' is not set to 0, bloom effect disabled\n"); + return; + } + if (backEnd.doneBloom) + return; + if (!backEnd.doneSurfaces) + return; + if (!clientIsConnected) + return; + backEnd.doneBloom = qtrue; + if (!bloom.started) { + R_Bloom_InitTextures(); + if (!bloom.started) + return; + } + if (!backEnd.projection2D) + RB_SetGL2D(); +#if 0 + // set up full screen workspace + GL_TexEnv(GL_MODULATE); + qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); + qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight); + qglMatrixMode(GL_PROJECTION); + qglLoadIdentity(); + qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1); + qglMatrixMode(GL_MODELVIEW); + qglLoadIdentity(); + + GL_Cull(CT_TWO_SIDED); +#endif + + qglColor4f(1, 1, 1, 1); + + //Backup the old screen in a texture + R_Bloom_BackupScreen(); + // create the bloom texture using one of a few methods + R_Bloom_WarsowEffect(); + // R_Bloom_CreateEffect(); + // restore the screen-backup to the screen + R_Bloom_RestoreScreen(); + // Do the final pass using the bloom texture for the final effect + R_Bloom_DrawEffect(); +} + + +void R_BloomInit(void) { + memset(&bloom, 0, sizeof(bloom)); + + r_bloom = ri.Cvar_Get("r_bloom", "0", CVAR_ARCHIVE); + r_bloom_alpha = ri.Cvar_Get("r_bloom_alpha", "0.3", CVAR_ARCHIVE); + r_bloom_diamond_size = ri.Cvar_Get("r_bloom_diamond_size", "8", CVAR_ARCHIVE); + r_bloom_intensity = ri.Cvar_Get("r_bloom_intensity", "1.3", CVAR_ARCHIVE); + r_bloom_darken = ri.Cvar_Get("r_bloom_darken", "4", CVAR_ARCHIVE); + r_bloom_sample_size = ri.Cvar_Get("r_bloom_sample_size", "128", CVAR_ARCHIVE | CVAR_LATCH); + r_bloom_fast_sample = ri.Cvar_Get("r_bloom_fast_sample", "0", CVAR_ARCHIVE | CVAR_LATCH); +} + diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c index 09088acf..ed09667f 100644 --- a/src/renderer/tr_bsp.c +++ b/src/renderer/tr_bsp.c @@ -141,7 +141,7 @@ R_LoadLightmaps static void R_LoadLightmaps( lump_t *l ) { byte *buf, *buf_p; int len; - MAC_STATIC byte image[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4]; + byte image[LIGHTMAP_SIZE * LIGHTMAP_SIZE * 4]; int i, j; float maxIntensity = 0; double sumIntensity = 0; @@ -179,7 +179,7 @@ static void R_LoadLightmaps( lump_t *l ) { float g = buf_p[j * 3 + 1]; float b = buf_p[j * 3 + 2]; float intensity; - float out[3]; + float out[3] = {0.0, 0.0, 0.0}; intensity = 0.33f * r + 0.685f * g + 0.063f * b; @@ -288,12 +288,6 @@ static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) { lightmapNum = LIGHTMAP_BY_VERTEX; } -// JPW NERVE removed per atvi request -/* - if ( r_fullbright->integer ) { - lightmapNum = LIGHTMAP_WHITEIMAGE; - } -*/ shader = R_FindShader( dsh->shader, lightmapNum, qtrue ); // if the shader had errors, just use default shader @@ -378,7 +372,7 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int numIndexes = LittleLong( ds->numIndexes ); // create the srfSurfaceFace_t - sfaceSize = ( int ) &( (srfSurfaceFace_t *)0 )->points[numPoints]; + sfaceSize = ( size_t )&((srfSurfaceFace_t *)0)->points[numPoints]; ofsIndexes = sfaceSize; sfaceSize += sizeof( int ) * numIndexes; @@ -428,7 +422,7 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) { srfGridMesh_t *grid; int i, j; int width, height, numPoints; - MAC_STATIC drawVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE]; + drawVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE]; int lightmapNum; vec3_t bounds[2]; vec3_t tmpVec; @@ -1452,7 +1446,7 @@ void R_MovePatchSurfacesToHunk( void ) { Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 ); hunkgrid->heightLodError = ri.Hunk_Alloc( grid->height * 4, h_low ); - Com_Memcpy( grid->heightLodError, grid->heightLodError, grid->height * 4 ); + Com_Memcpy(hunkgrid->heightLodError, grid->heightLodError, grid->height * 4); R_FreeSurfaceGridMesh( grid ); @@ -1568,6 +1562,9 @@ static void R_LoadSubmodels( lump_t *l ) { model = R_AllocModel(); assert( model != NULL ); // this should never happen + if (model == NULL) { + ri.Error(ERR_DROP, "R_LoadSubmodels: R_AllocModel() failed"); + } model->type = MOD_BRUSH; model->bmodel = out; diff --git a/src/renderer/tr_cmds.c b/src/renderer/tr_cmds.c index a853adb9..1daf0676 100644 --- a/src/renderer/tr_cmds.c +++ b/src/renderer/tr_cmds.c @@ -436,6 +436,15 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { r_textureMode->modified = qfalse; } + // + // anisotropic filtering stuff + // + if (r_textureAnisotropy->modified) { + R_SyncRenderThread(); + GL_TextureAnisotropy(r_textureAnisotropy->value); + r_textureAnisotropy->modified = qfalse; + } + // // NVidia stuff // diff --git a/src/renderer/tr_curve.c b/src/renderer/tr_curve.c index 35e672a2..a09ae2f8 100644 --- a/src/renderer/tr_curve.c +++ b/src/renderer/tr_curve.c @@ -120,7 +120,7 @@ static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZ int i, j, k, dist; vec3_t normal; vec3_t sum; - int count; + int count = 0; vec3_t base; vec3_t delta; int x, y; @@ -211,10 +211,6 @@ static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZ VectorAdd( normal, sum, sum ); count++; } - if ( count == 0 ) { -//printf("bad normal\n"); - count = 1; - } VectorNormalize2( sum, dv->normal ); } } @@ -367,11 +363,13 @@ R_SubdividePatchToGrid srfGridMesh_t *R_SubdividePatchToGrid( int width, int height, drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) { int i, j, k, l; - drawVert_t prev, next, mid; + drawVert_t_cleared(prev); + drawVert_t_cleared(next); + drawVert_t_cleared(mid); float len, maxLen; int dir; int t; - MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; + drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; float errorTable[2][MAX_GRID_SIZE]; for ( i = 0 ; i < width ; i++ ) { @@ -529,7 +527,7 @@ R_GridInsertColumn srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) { int i, j; int width, height, oldwidth; - MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; + drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; float errorTable[2][MAX_GRID_SIZE]; float lodRadius; vec3_t lodOrigin; @@ -585,7 +583,7 @@ R_GridInsertRow srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) { int i, j; int width, height, oldheight; - MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; + drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE]; float errorTable[2][MAX_GRID_SIZE]; float lodRadius; vec3_t lodOrigin; diff --git a/src/renderer/tr_flares.c b/src/renderer/tr_flares.c index e40e079e..ea7a8d8c 100644 --- a/src/renderer/tr_flares.c +++ b/src/renderer/tr_flares.c @@ -83,17 +83,19 @@ typedef struct flare_s { int windowX, windowY; float eyeZ; + vec3_t origin; vec3_t color; float scale; int id; } flare_t; -#define MAX_FLARES 128 +#define MAX_FLARES 256 flare_t r_flareStructs[MAX_FLARES]; flare_t *r_activeFlares, *r_inactiveFlares; +int flareCoeff; /* ================== @@ -123,17 +125,26 @@ This is called at surface tesselation time */ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float scale, vec3_t normal, int id, qboolean cgvisible ) { //----(SA) added scale. added id. added visible int i; - flare_t *f, *oldest; + flare_t *f; vec3_t local; - float d; + float d = 1; vec4_t eye, clip, normalized, window; backEnd.pc.c_flareAdds++; + if (normal && (normal[0] || normal[1] || normal[2])) { + VectorSubtract(backEnd.viewParms. or .origin, point, local); + VectorNormalizeFast(local); + d = DotProduct(local, normal); + + // If the viewer is behind the flare don't add it. + if (d < 0) + return; + } + // if the point is off the screen, don't bother adding it // calculate screen coordinates and depth - R_TransformModelToClip( point, backEnd.or.modelMatrix, - backEnd.viewParms.projectionMatrix, eye, clip ); + R_TransformModelToClip(point, backEnd. or .modelMatrix, backEnd.viewParms.projectionMatrix, eye, clip); //ri.Printf(PRINT_ALL, "src: %f %f %f \n", point[0], point[1], point[2]); //ri.Printf(PRINT_ALL, "eye: %f %f %f %f\n", eye[0], eye[1], eye[2], eye[3]); @@ -155,8 +166,7 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float s } // see if a flare with a matching surface, scene, and view exists - oldest = r_flareStructs; - for ( f = r_activeFlares ; f ; f = f->next ) { + for ( f = r_activeFlares; f; f = f->next ) { // if ( f->surface == surface && f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal ) { // (SA) added back in more checks for different scenes @@ -193,18 +203,14 @@ void RB_AddFlare( void *surface, int fogNum, vec3_t point, vec3_t color, float s f->addedFrame = backEnd.viewParms.frameCount; f->fogNum = fogNum; + VectorCopy( point, f->origin ); VectorCopy( color, f->color ); f->scale = scale; //----(SA) // fade the intensity of the flare down as the // light surface turns away from the viewer - if ( normal ) { - VectorSubtract( backEnd.viewParms.or.origin, point, local ); - VectorNormalizeFast( local ); - d = DotProduct( local, normal ); - VectorScale( f->color, d, f->color ); - } + VectorScale(f->color, d, f->color); // save info needed to test f->windowX = backEnd.viewParms.viewportX + window[0]; @@ -219,36 +225,43 @@ RB_AddDlightFlares ================== */ void RB_AddDlightFlares( void ) { - dlight_t *l; + dlight_t *l; int i, j, k; int id = 0; - fog_t *fog; + fog_t *fog = NULL; if ( r_flares->integer < 2 ) { return; } l = backEnd.refdef.dlights; - fog = tr.world->fogs; - for ( i = 0 ; i < backEnd.refdef.num_dlights ; i++, l++ ) { + if (tr.world) + fog = tr.world->fogs; + + for (i = 0; i < backEnd.refdef.num_dlights; i++, l++) { // find which fog volume the light is in - for ( j = 1 ; j < tr.world->numfogs ; j++ ) { - fog = &tr.world->fogs[j]; - for ( k = 0 ; k < 3 ; k++ ) { - if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) { + if (fog) { + // find which fog volume the light is in + for (j = 1; j < tr.world->numfogs; j++) { + fog = &tr.world->fogs[j]; + for (k = 0; k < 3; k++) { + if (l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k]) { + break; + } + } + if (k == 3) { break; } } - if ( k == 3 ) { - break; + if (j == tr.world->numfogs) { + j = 0; } } - if ( j == tr.world->numfogs ) { + else j = 0; - } - RB_AddFlare( (void *)l, j, l->origin, l->color, 1.0f, NULL, id++, qtrue ); //----(SA) also set scale + RB_AddFlare((void*)l, j, l->origin, l->color, 1.0f, NULL, id++, qtrue); //----(SA) also set scale } } @@ -308,31 +321,11 @@ RB_TestFlare ================== */ void RB_TestFlare( flare_t *f ) { -// float depth; qboolean visible; float fade; -// float screenZ; backEnd.pc.c_flareTests++; - // doing a readpixels is as good as doing a glFinish(), so - // don't bother with another sync -// glState.finishCalled = qfalse; -// glState.finishCalled = qtrue; // (SA) Hmm, shouldn't this be true? - - // read back the z buffer contents -// qglReadPixels( f->windowX, f->windowY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth ); -// screenZ = backEnd.viewParms.projectionMatrix[14] / -// ( ( 2*depth - 1 ) * backEnd.viewParms.projectionMatrix[11] - backEnd.viewParms.projectionMatrix[10] ); - - //----(SA) 24 was way to low tolerance. It gave Dan problems with free standing light fixtures - //----(SA) I will monitor to see if changing this screws up any other situations - //----(SA) and 2 was way to high tolerance -// visible = ( -f->eyeZ - -screenZ ) < 2; -// visible = ( -f->eyeZ - -screenZ ) < 24; -// visible = ( -f->eyeZ - -screenZ ) < 6; - -// visible = qtrue; visible = f->cgvisible; if ( visible ) { @@ -341,7 +334,8 @@ void RB_TestFlare( flare_t *f ) { f->fadeTime = backEnd.refdef.time - 1; } fade = ( ( backEnd.refdef.time - f->fadeTime ) / 1000.0f ) * r_flareFade->value; - } else { + } + else { if ( f->visible ) { f->visible = qfalse; f->fadeTime = backEnd.refdef.time - 1; @@ -359,7 +353,6 @@ void RB_TestFlare( flare_t *f ) { f->drawIntensity = fade; } - /* ================== RB_RenderFlare @@ -369,26 +362,64 @@ void RB_RenderFlare( flare_t *f ) { float size; vec3_t color; int iColor[3]; + float distance, intensity, factor; + byte fogFactors[3] = {255, 255, 255}; backEnd.pc.c_flareRenders++; -//----(SA) changed to use alpha blend rather than additive blend -// this is to accomidate the fact we can't right now do -// additive blends and have them fog correctly with our distance fog. -// /when/ we fix the blend problems with distance fog, this should -// be changed back to additive since there's nearly no hit for that -// but the alpha blend is noticably slower. - -// VectorScale( f->color, f->drawIntensity*tr.identityLight, color ); - VectorScale( f->color, tr.identityLight, color ); //----(SA) mod for alpha blend rather than additive - - iColor[0] = color[0] * 255; - iColor[1] = color[1] * 255; - iColor[2] = color[2] * 255; + // We don't want too big values anyways when dividing by distance. + if (f->eyeZ > -1.0f) + distance = 1.0f; + else + distance = -f->eyeZ; + + // calculate the flare size.. + size = backEnd.viewParms.viewportWidth * (r_flareSize->value / 640.0f + 8 / distance); + + /* + * This is an alternative to intensity scaling. It changes the size of the flare on screen instead + * with growing distance. See in the description at the top why this is not the way to go. + // size will change ~ 1/r. + size = backEnd.viewParms.viewportWidth * (r_flareSize->value / (distance * -2.0f)); + */ + + /* + * As flare sizes stay nearly constant with increasing distance we must decrease the intensity + * to achieve a reasonable visual result. The intensity is ~ (size^2 / distance^2) which can be + * got by considering the ratio of + * (flaresurface on screen) : (Surface of sphere defined by flare origin and distance from flare) + * An important requirement is: + * intensity <= 1 for all distances. + * + * The formula used here to compute the intensity is as follows: + * intensity = flareCoeff * size^2 / (distance + size*sqrt(flareCoeff))^2 + * As you can see, the intensity will have a max. of 1 when the distance is 0. + * The coefficient flareCoeff will determine the falloff speed with increasing distance. + */ + + factor = distance + size * sqrt(flareCoeff); + intensity = flareCoeff * size * size / (factor * factor); + + VectorScale(f->color, f->drawIntensity * intensity, color); + + // Calculations for fogging + if (tr.world && f->fogNum > 0 && f->fogNum < tr.world->numfogs) { + tess.numVertexes = 1; + VectorCopy(f->origin, tess.xyz[0]); + tess.fogNum = f->fogNum; + + RB_CalcModulateColorsByFog(fogFactors); + + // We don't need to render the flare if colors are 0 anyways. + if (!(fogFactors[0] || fogFactors[1] || fogFactors[2])) + return; + } - size = backEnd.viewParms.viewportWidth * ( ( r_flareSize->value * f->scale ) / 640.0 + 8 / -f->eyeZ ); + iColor[0] = color[0] * fogFactors[0]; + iColor[1] = color[1] * fogFactors[1]; + iColor[2] = color[2] * fogFactors[2]; - RB_BeginSurface( tr.flareShader, f->fogNum ); + RB_BeginSurface(tr.flareShader, f->fogNum); // FIXME: use quadstamp? tess.xyz[tess.numVertexes][0] = f->windowX - size; @@ -470,6 +501,20 @@ void RB_RenderFlares( void ) { return; } + if (r_flareCoeff->modified) { + if (r_flareCoeff->value == 0.0f) + flareCoeff = atof(FLARE_STDCOEFF); + else + flareCoeff = r_flareCoeff->value; + + r_flareCoeff->modified = qfalse; + } + + // Reset currentEntity to world so that any previously referenced entities + // don't have influence on the rendering of these flares (i.e. RF_ renderer flags). + backEnd.currentEntity = &tr.worldEntity; + backEnd. or = backEnd.viewParms.world; + // (SA) turned light flares back on. must evaluate problem id had with this RB_AddDlightFlares(); RB_AddCoronaFlares(); @@ -493,7 +538,8 @@ void RB_RenderFlares( void ) { RB_TestFlare( f ); if ( f->drawIntensity ) { draw = qtrue; - } else { + } + else { // this flare has completely faded out, so remove it from the chain *prev = f->next; f->next = r_inactiveFlares; diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c index 18eb1b49..2dbe3aaf 100644 --- a/src/renderer/tr_image.c +++ b/src/renderer/tr_image.c @@ -57,6 +57,8 @@ static unsigned char s_gammatable[256]; int gl_filter_min = GL_LINEAR_MIPMAP_NEAREST; int gl_filter_max = GL_LINEAR; +float gl_anisotropy = 1.0; // L0 - ET port + #define FILE_HASH_SIZE 4096 static image_t* hashTable[FILE_HASH_SIZE]; @@ -202,6 +204,38 @@ void GL_TextureMode( const char *string ) { } } +/* +=============== +L0 - ET port + +GL_TextureAnisotropy +=============== +*/ +void GL_TextureAnisotropy(float anisotropy) { + int i; + image_t* glt; + + if (r_ext_texture_filter_anisotropic->integer == 1) { + if (anisotropy < 1.0 || anisotropy > glConfig.maxAnisotropy) { + ri.Printf(PRINT_ALL, "anisotropy out of range\n"); + return; + } + } + + gl_anisotropy = anisotropy; + + if (!glConfig.anisotropicAvailable) { + return; + } + + // change all the existing texture objects + for (i = 0; i < tr.numImages; i++) { + glt = tr.images[i]; + GL_Bind(glt); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy); + } +} + /* =============== R_SumOfUsedImages @@ -820,6 +854,10 @@ static void Upload32( unsigned *data, qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); } + if (glConfig.anisotropicAvailable) { + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_anisotropy); + } + GL_CheckErrors(); //if ( scaledBuffer != 0 ) @@ -862,6 +900,11 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height noCompress = qtrue; } + // ydnar: don't compress textures smaller or equal to 128x128 pixels + if ((width * height) <= (128 * 128)) { + noCompress = qtrue; + } + if ( tr.numImages == MAX_DRAWIMAGES ) { ri.Error( ERR_DROP, "R_CreateImage: MAX_DRAWIMAGES hit\n" ); } @@ -869,14 +912,15 @@ image_t *R_CreateImage( const char *name, const byte *pic, int width, int height // Ridah image = tr.images[tr.numImages] = R_CacheImageAlloc( sizeof( image_t ) ); - image->texnum = 1024 + tr.numImages; - // Ridah if ( r_cacheShaders->integer ) { R_FindFreeTexnum( image ); } // done. + // ydnar: ok, let's try the recommended way + qglGenTextures(1, &image->texnum); + tr.numImages++; image->mipmap = mipmap; @@ -1120,12 +1164,16 @@ PCX LOADING /* ============== LoadPCX + +L0 - ET port (patched existing) ============== */ +#define DECODEPCX( b, d, r ) d = *b++; if ( ( d & 0xC0 ) == 0xC0 ) {r = d & 0x3F; d = *b++;} else {r = 1;} + static void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height ) { byte *raw; pcx_t *pcx; - int x, y; + int x, y, lsize; int len; int dataByte, runLength; byte *out, *pix; @@ -1133,6 +1181,7 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt *pic = NULL; *palette = NULL; + runLength = 0; // // load the file @@ -1180,23 +1229,24 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt } // FIXME: use bytes_per_line here? - for ( y = 0 ; y <= ymax ; y++, pix += xmax + 1 ) - { - for ( x = 0 ; x <= xmax ; ) - { - dataByte = *raw++; + lsize = pcx->color_planes * pcx->bytes_per_line; - if ( ( dataByte & 0xC0 ) == 0xC0 ) { - runLength = dataByte & 0x3F; - dataByte = *raw++; - } else { - runLength = 1; - } - - while ( runLength-- > 0 ) + // go scanline by scanline + for (y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1) { + // do a scanline + for (x = 0; x <= pcx->xmax;) { + DECODEPCX(raw, dataByte, runLength); + while (runLength-- > 0) pix[x++] = dataByte; } + // discard any other data + while (x < lsize) { + DECODEPCX(raw, dataByte, runLength); + x++; + } + while (runLength-- > 0) + x++; } if ( raw - (byte *)pcx > len ) { @@ -1208,7 +1258,6 @@ static void LoadPCX( const char *filename, byte **pic, byte **palette, int *widt ri.FS_FreeFile( pcx ); } - /* ============== LoadPCX32 @@ -2293,11 +2342,23 @@ void R_SetColorMappings( void ) { ri.Cvar_Set( "r_intensity", "1" ); } - if ( r_gamma->value < 0.5f ) { - ri.Cvar_Set( "r_gamma", "0.5" ); - } else if ( r_gamma->value > 3.0f ) { - ri.Cvar_Set( "r_gamma", "3.0" ); +#ifdef __linux__ + if (r_gamma->value != -1) { +#endif + if (r_gamma->value < 0.5f) { + ri.Cvar_Set("r_gamma", "0.5"); + } + else if (r_gamma->value > 3.0f) { + ri.Cvar_Set("r_gamma", "3.0"); + } + g = r_gamma->value; + +#ifdef __linux__ + } + else { + g = 1.0f; } +#endif g = r_gamma->value; @@ -2548,7 +2609,10 @@ qhandle_t RE_GetShaderFromModel( qhandle_t modelid, int surfnum, int withlightma } surf = bmodel->firstSurface + surfnum; -// if(surf->shader->lightmapIndex != LIGHTMAP_NONE) { + // RF, check for null shader (can happen on func_explosive's with botclips attached) + if (!surf->shader) { + return 0; + } if ( surf->shader->lightmapIndex > LIGHTMAP_NONE ) { image_t *image; long hash; diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c index 2cf79ad8..af5a56af 100644 --- a/src/renderer/tr_init.c +++ b/src/renderer/tr_init.c @@ -42,6 +42,7 @@ static void GfxInfo_f( void ); cvar_t *r_flareSize; cvar_t *r_flareFade; +cvar_t* r_flareCoeff; cvar_t *r_railWidth; cvar_t *r_railCoreWidth; @@ -140,6 +141,7 @@ cvar_t *r_finish; cvar_t *r_clear; cvar_t *r_swapInterval; cvar_t *r_textureMode; +cvar_t *r_textureAnisotropy; cvar_t *r_offsetFactor; cvar_t *r_offsetUnits; cvar_t *r_gamma; @@ -371,18 +373,30 @@ typedef struct vidmode_s vidmode_t r_vidModes[] = { - { "Mode 0: 320x240", 320, 240, 1 }, - { "Mode 1: 400x300", 400, 300, 1 }, - { "Mode 2: 512x384", 512, 384, 1 }, - { "Mode 3: 640x480", 640, 480, 1 }, - { "Mode 4: 800x600", 800, 600, 1 }, - { "Mode 5: 960x720", 960, 720, 1 }, - { "Mode 6: 1024x768", 1024, 768, 1 }, - { "Mode 7: 1152x864", 1152, 864, 1 }, - { "Mode 8: 1280x1024", 1280, 1024, 1 }, - { "Mode 9: 1600x1200", 1600, 1200, 1 }, - { "Mode 10: 2048x1536", 2048, 1536, 1 }, - { "Mode 11: 856x480 (wide)",856, 480, 1 } + // L0 - modifed and updated resolutions.. + { "Mode 0: 320x240", 320, 240, 1 }, + { "Mode 1: 400x300", 400, 300, 1 }, + { "Mode 2: 512x384", 512, 384, 1 }, + { "Mode 3: 640x480", 640, 480, 1 }, + { "Mode 4: 800x600", 800, 600, 1 }, + { "Mode 5: 856x480 (wide)", 856, 480, 1 }, + { "Mode 6: 960x720", 960, 720, 1 }, + { "Mode 7: 1024x768", 1024, 768, 1 }, + { "Mode 8: 1152x864", 1152, 864, 1 }, + { "Mode 9: 1280x720 (16:9)", 1280, 720, 1 }, + { "Mode 10: 1280x768 (16:10)", 1280, 768, 1 }, + { "Mode 11: 1280x800 (16:10)", 1280, 800, 1 }, + { "Mode 12: 1280x1024", 1280, 1024, 1 }, + { "Mode 13: 1360x768 (16:9)", 1360, 768, 1 }, + { "Mode 14: 1440x900 (16:10)", 1440, 900, 1 }, + { "Mode 15: 1680x1050 (16:10)", 1680, 1050, 1 }, + { "Mode 16: 1600x1200", 1600, 1200, 1 }, + { "Mode 17: 1920x1080 (FULL HD)", 1920, 1080, 1 }, + { "Mode 18: 1920x1200", 1920, 1200, 1 }, + { "Mode 19: 2048x1536", 2048, 1536, 1 }, + { "Mode 20: 2560x1440 (QHD)", 2560, 1440, 1 }, + { "Mode 21: 2560x1600 (16:10)", 2560, 1600, 1 }, + { "Mode 22: 3840x2160 (UHD)", 3840, 2160, 1 } }; static int s_numVidModes = ( sizeof( r_vidModes ) / sizeof( r_vidModes[0] ) ); @@ -751,6 +765,7 @@ void GL_SetDefaultState( void ) { if ( qglActiveTextureARB ) { GL_SelectTexture( 1 ); GL_TextureMode( r_textureMode->string ); + GL_TextureAnisotropy(r_textureAnisotropy->value); GL_TexEnv( GL_MODULATE ); qglDisable( GL_TEXTURE_2D ); GL_SelectTexture( 0 ); @@ -758,6 +773,7 @@ void GL_SetDefaultState( void ) { qglEnable( GL_TEXTURE_2D ); GL_TextureMode( r_textureMode->string ); + GL_TextureAnisotropy(r_textureAnisotropy->value); GL_TexEnv( GL_MODULATE ); qglShadeModel( GL_SMOOTH ); @@ -834,9 +850,7 @@ void GfxInfo_f( void ) { ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string ); ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string ); ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string ); - ri.Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", glConfig.extensions_string ); ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize ); - ri.Printf( PRINT_ALL, "GL_MAX_ACTIVE_TEXTURES_ARB: %d\n", glConfig.maxActiveTextures ); ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s hz:", r_mode->integer, glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen->integer == 1] ); if ( glConfig.displayFrequency ) { @@ -885,6 +899,7 @@ void GfxInfo_f( void ) { ri.Printf( PRINT_ALL, "compiled vertex arrays: %s\n", enablestrings[qglLockArraysEXT != 0 ] ); ri.Printf( PRINT_ALL, "texenv add: %s\n", enablestrings[glConfig.textureEnvAddAvailable != 0] ); ri.Printf( PRINT_ALL, "compressed textures: %s\n", enablestrings[glConfig.textureCompression != TC_NONE] ); + ri.Printf( PRINT_ALL, "anisotropy: %s\n", r_textureAnisotropy->string ); ri.Printf( PRINT_ALL, "NV distance fog: %s\n", enablestrings[glConfig.NVFogAvailable != 0] ); if ( glConfig.NVFogAvailable ) { @@ -947,7 +962,7 @@ void R_Register( void ) { r_picmip = ri.Cvar_Get( "r_picmip", "1", CVAR_ARCHIVE | CVAR_LATCH ); //----(SA) mod for DM and DK for id build. was "1" // JPW NERVE pushed back to 1 r_roundImagesDown = ri.Cvar_Get( "r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_rmse = ri.Cvar_Get( "r_rmse", "0.0", CVAR_ARCHIVE | CVAR_LATCH ); + r_rmse = ri.Cvar_Get( "r_rmse", "0.0", CVAR_CHEAT); r_colorMipLevels = ri.Cvar_Get( "r_colorMipLevels", "0", CVAR_LATCH ); AssertCvarRange( r_picmip, 0, 16, qtrue ); r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH ); @@ -962,7 +977,7 @@ void R_Register( void ) { r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_overBrightBits = ri.Cvar_Get( "r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_ignorehwgamma = ri.Cvar_Get( "r_ignorehwgamma", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_mode = ri.Cvar_Get( "r_mode", "3", CVAR_ARCHIVE | CVAR_LATCH ); + r_mode = ri.Cvar_Get( "r_mode", "4", CVAR_ARCHIVE | CVAR_LATCH ); r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_customwidth = ri.Cvar_Get( "r_customwidth", "1600", CVAR_ARCHIVE | CVAR_LATCH ); r_customheight = ri.Cvar_Get( "r_customheight", "1024", CVAR_ARCHIVE | CVAR_LATCH ); @@ -974,6 +989,10 @@ void R_Register( void ) { #ifdef MACOS_X // Default to using SMP on Mac OS X if we have multiple processors r_smp = ri.Cvar_Get( "r_smp", Sys_ProcessorCount() > 1 ? "1" : "0", CVAR_ARCHIVE | CVAR_LATCH ); +#elif defined WIN32 + // ydnar: r_smp is nonfunctional on windows + r_smp = ri.Cvar_Get("r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH | CVAR_ROM); + Cvar_Set("r_smp", "0"); #else r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH ); #endif @@ -1011,6 +1030,7 @@ void R_Register( void ) { r_dlightBacks = ri.Cvar_Get( "r_dlightBacks", "1", CVAR_ARCHIVE ); r_finish = ri.Cvar_Get( "r_finish", "0", CVAR_ARCHIVE ); r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE ); + r_textureAnisotropy = ri.Cvar_Get("r_textureAnisotropy", "1.0", CVAR_ARCHIVE); r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE ); #ifdef __MACOS__ r_gamma = ri.Cvar_Get( "r_gamma", "1.2", CVAR_ARCHIVE ); @@ -1043,7 +1063,7 @@ void R_Register( void ) { // with r_cache enabled, non-win32 OSes were leaking 24Mb per R_Init.. r_cache = ri.Cvar_Get( "r_cache", "1", CVAR_LATCH ); // leaving it as this for backwards compability. but it caches models and shaders also // TTimo show_bug.cgi?id=570 - r_cacheShaders = ri.Cvar_Get( "r_cacheShaders", "1", CVAR_LATCH ); + r_cacheShaders = ri.Cvar_Get( "r_cacheShaders", "0", CVAR_LATCH ); r_cacheModels = ri.Cvar_Get( "r_cacheModels", "1", CVAR_LATCH ); r_compressModels = ri.Cvar_Get( "r_compressModels", "0", 0 ); // converts MD3 -> MDC at run-time @@ -1065,6 +1085,7 @@ void R_Register( void ) { r_flareSize = ri.Cvar_Get( "r_flareSize", "40", CVAR_CHEAT ); ri.Cvar_Set( "r_flareFade", "5" ); // to force this when people already have "7" in their config r_flareFade = ri.Cvar_Get( "r_flareFade", "5", CVAR_CHEAT ); + r_flareCoeff = ri.Cvar_Get("r_flareCoeff", FLARE_STDCOEFF, CVAR_CHEAT); r_showSmp = ri.Cvar_Get( "r_showSmp", "0", CVAR_CHEAT ); r_skipBackEnd = ri.Cvar_Get( "r_skipBackEnd", "0", CVAR_CHEAT ); @@ -1174,6 +1195,8 @@ void R_Init( void ) { R_Register(); + R_BloomInit(); + max_polys = r_maxpolys->integer; if ( max_polys < MAX_POLYS ) { max_polys = MAX_POLYS; diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h index 60219fed..f2731d06 100644 --- a/src/renderer/tr_local.h +++ b/src/renderer/tr_local.h @@ -25,9 +25,6 @@ If you have questions concerning this license or the applicable additional terms =========================================================================== */ - - - #ifndef TR_LOCAL_H #define TR_LOCAL_H @@ -923,6 +920,10 @@ typedef struct { byte color2D[4]; qboolean vertexes2D; // shader needs to be finished trRefEntity_t entity2D; // currentEntity will point at this when doing 2D rendering + + // L0 - Bloom + qboolean doneBloom; // done bloom this frame + qboolean doneSurfaces; // done any 3d surfaces already } backEndState_t; /* @@ -1048,6 +1049,8 @@ extern glstate_t glState; // outside of TR since it shouldn't be clear // extern cvar_t *r_flareSize; extern cvar_t *r_flareFade; +#define FLARE_STDCOEFF "150" // coefficient for the flare intensity falloff function. +extern cvar_t* r_flareCoeff; extern cvar_t *r_railWidth; extern cvar_t *r_railCoreWidth; @@ -1139,6 +1142,7 @@ extern cvar_t *r_glDriver; extern cvar_t *r_glIgnoreWicked3D; extern cvar_t *r_swapInterval; extern cvar_t *r_textureMode; +extern cvar_t *r_textureAnisotropy; extern cvar_t *r_offsetFactor; extern cvar_t *r_offsetUnits; @@ -1241,6 +1245,7 @@ void GL_Bind( image_t *image ); void GL_SetDefaultState( void ); void GL_SelectTexture( int unit ); void GL_TextureMode( const char *string ); +void GL_TextureAnisotropy(float anisotropy); void GL_CheckErrors( void ); void GL_State( unsigned long stateVector ); void GL_TexEnv( int env ); @@ -1410,6 +1415,7 @@ typedef struct shaderCommands_s extern shaderCommands_t tess; +void RB_SetGL2D(void); void RB_BeginSurface( shader_t *shader, int fogNum ); void RB_EndSurface( void ); void RB_CheckOverflow( int verts, int indexes ); @@ -1737,6 +1743,10 @@ void R_InitFreeType(); void R_DoneFreeType(); void RE_RegisterFont( const char *fontName, int pointSize, fontInfo_t *font ); +// L0 - Bloom +void R_BloomInit(void); +void R_BloomScreen(void); + // Ridah, caching system // NOTE: to disable this for development, set "r_cache 0" in autoexec.cfg void R_InitTexnumImages( qboolean force ); diff --git a/src/renderer/tr_main.c b/src/renderer/tr_main.c index b9efd737..4109ba1f 100644 --- a/src/renderer/tr_main.c +++ b/src/renderer/tr_main.c @@ -850,6 +850,12 @@ void R_SetupFrustum( void ) { tr.viewParms.frustum[i].dist = DotProduct( tr.viewParms.or.origin, tr.viewParms.frustum[i].normal ); SetPlaneSignbits( &tr.viewParms.frustum[i] ); } + + // ydnar: farplane (testing! use farplane for real) + VectorScale(tr.viewParms. or .axis[0], -1, tr.viewParms.frustum[4].normal); + tr.viewParms.frustum[4].dist = DotProduct(tr.viewParms. or .origin, tr.viewParms.frustum[4].normal) - tr.viewParms.zFar; + tr.viewParms.frustum[4].type = PLANE_NON_AXIAL; + SetPlaneSignbits(&tr.viewParms.frustum[4]); } diff --git a/src/renderer/tr_marks.c b/src/renderer/tr_marks.c index 15667025..780a98d0 100644 --- a/src/renderer/tr_marks.c +++ b/src/renderer/tr_marks.c @@ -2,9 +2,9 @@ =========================================================================== Return to Castle Wolfenstein multiplayer GPL Source Code -Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. +Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company. -This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”). +This file is part of the Return to Castle Wolfenstein multiplayer GPL Source Code (“RTCW MP Source Code”). RTCW MP 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 @@ -49,19 +49,19 @@ Out must have space for two more vertexes than in #define SIDE_FRONT 0 #define SIDE_BACK 1 #define SIDE_ON 2 -static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY], - int *numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY], - vec3_t normal, vec_t dist, vec_t epsilon ) { +static void R_ChopPolyBehindPlane(int numInPoints, vec3_t inPoints[MAX_VERTS_ON_POLY], + int* numOutPoints, vec3_t outPoints[MAX_VERTS_ON_POLY], + vec3_t normal, vec_t dist, vec_t epsilon) { float dists[MAX_VERTS_ON_POLY + 4]; int sides[MAX_VERTS_ON_POLY + 4]; int counts[3]; float dot; int i, j; - float *p1, *p2, *clip; + float* p1, * p2, * clip; float d; // don't clip if it might overflow - if ( numInPoints >= MAX_VERTS_ON_POLY - 2 ) { + if (numInPoints >= MAX_VERTS_ON_POLY - 2) { *numOutPoints = 0; return; } @@ -69,15 +69,17 @@ static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON counts[0] = counts[1] = counts[2] = 0; // determine sides for each point - for ( i = 0 ; i < numInPoints ; i++ ) { - dot = DotProduct( inPoints[i], normal ); + for (i = 0; i < numInPoints; i++) { + dot = DotProduct(inPoints[i], normal); dot -= dist; dists[i] = dot; - if ( dot > epsilon ) { + if (dot > epsilon) { sides[i] = SIDE_FRONT; - } else if ( dot < -epsilon ) { + } + else if (dot < -epsilon) { sides[i] = SIDE_BACK; - } else { + } + else { sides[i] = SIDE_ON; } counts[sides[i]]++; @@ -87,52 +89,53 @@ static void R_ChopPolyBehindPlane( int numInPoints, vec3_t inPoints[MAX_VERTS_ON *numOutPoints = 0; - if ( !counts[0] ) { + if (!counts[0]) { return; } - if ( !counts[1] ) { + if (!counts[1]) { *numOutPoints = numInPoints; - memcpy( outPoints, inPoints, numInPoints * sizeof( vec3_t ) ); + memcpy(outPoints, inPoints, numInPoints * sizeof(vec3_t)); return; } - for ( i = 0 ; i < numInPoints ; i++ ) { + for (i = 0; i < numInPoints; i++) { p1 = inPoints[i]; - clip = outPoints[ *numOutPoints ]; + clip = outPoints[*numOutPoints]; - if ( sides[i] == SIDE_ON ) { - VectorCopy( p1, clip ); - ( *numOutPoints )++; + if (sides[i] == SIDE_ON) { + VectorCopy(p1, clip); + (*numOutPoints)++; continue; } - if ( sides[i] == SIDE_FRONT ) { - VectorCopy( p1, clip ); - ( *numOutPoints )++; - clip = outPoints[ *numOutPoints ]; + if (sides[i] == SIDE_FRONT) { + VectorCopy(p1, clip); + (*numOutPoints)++; + clip = outPoints[*numOutPoints]; } - if ( sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i] ) { + if (sides[i + 1] == SIDE_ON || sides[i + 1] == sides[i]) { continue; } // generate a split point - p2 = inPoints[ ( i + 1 ) % numInPoints ]; + p2 = inPoints[(i + 1) % numInPoints]; d = dists[i] - dists[i + 1]; - if ( d == 0 ) { + if (d == 0) { dot = 0; - } else { + } + else { dot = dists[i] / d; } // clip xyz - for ( j = 0 ; j < 3 ; j++ ) { - clip[j] = p1[j] + dot * ( p2[j] - p1[j] ); + for (j = 0; j < 3; j++) { + clip[j] = p1[j] + dot * (p2[j] - p1[j]); } - ( *numOutPoints )++; + (*numOutPoints)++; } } @@ -142,68 +145,75 @@ R_BoxSurfaces_r ================= */ -void R_BoxSurfaces_r( mnode_t *node, vec3_t mins, vec3_t maxs, surfaceType_t **list, int listsize, int *listlength, vec3_t dir ) { +void R_BoxSurfaces_r(mnode_t* node, vec3_t mins, vec3_t maxs, surfaceType_t** list, int listsize, int* listlength, vec3_t dir) { int s, c; - msurface_t *surf, **mark; + msurface_t* surf, ** mark; // RF, if this node hasn't been rendered recently, ignore it - if ( node->visframe < tr.visCount - 2 ) { // allow us to be a few frames behind + if (node->visframe < tr.visCount - 2) { // allow us to be a few frames behind return; } // do the tail recursion in a loop - while ( node->contents == -1 ) { - s = BoxOnPlaneSide( mins, maxs, node->plane ); - if ( s == 1 ) { + while (node->contents == -1) { + s = BoxOnPlaneSide(mins, maxs, node->plane); + if (s == 1) { node = node->children[0]; - } else if ( s == 2 ) { + } + else if (s == 2) { node = node->children[1]; - } else { - R_BoxSurfaces_r( node->children[0], mins, maxs, list, listsize, listlength, dir ); + } + else { + R_BoxSurfaces_r(node->children[0], mins, maxs, list, listsize, listlength, dir); node = node->children[1]; } } // Ridah, don't mark alpha surfaces - if ( node->contents & CONTENTS_TRANSLUCENT ) { + if (node->contents & CONTENTS_TRANSLUCENT) { return; } // add the individual surfaces mark = node->firstmarksurface; c = node->nummarksurfaces; - while ( c-- ) { + while (c--) { // - if ( *listlength >= listsize ) { + if (*listlength >= listsize) { break; } // surf = *mark; // check if the surface has NOIMPACT or NOMARKS set - if ( ( surf->shader->surfaceFlags & ( SURF_NOIMPACT | SURF_NOMARKS ) ) - || ( surf->shader->contentFlags & CONTENTS_FOG ) ) { + if ((surf->shader->surfaceFlags & (SURF_NOIMPACT | SURF_NOMARKS)) + || (surf->shader->contentFlags & CONTENTS_FOG)) { surf->viewCount = tr.viewCount; } // extra check for surfaces to avoid list overflows - else if ( *( surf->data ) == SF_FACE ) { - // the face plane should go through the box - s = BoxOnPlaneSide( mins, maxs, &( ( srfSurfaceFace_t * ) surf->data )->plane ); - if ( s == 1 || s == 2 ) { - surf->viewCount = tr.viewCount; - } else if ( DotProduct( ( ( srfSurfaceFace_t * ) surf->data )->plane.normal, dir ) < -0.5 ) { - // don't add faces that make sharp angles with the projection direction - surf->viewCount = tr.viewCount; + else if (*(surf->data) == SF_FACE) { + if (((srfSurfaceFace_t*)surf->data)->plane.type != PLANE_NON_PLANAR) { + // the face plane should go through the box + s = BoxOnPlaneSide(mins, maxs, &((srfSurfaceFace_t*)surf->data)->plane); + if (s == 1 || s == 2) { + surf->viewCount = tr.viewCount; + } + else if (DotProduct(((srfSurfaceFace_t*)surf->data)->plane.normal, dir) < -0.5) { + // don't add faces that make sharp angles with the projection direction + surf->viewCount = tr.viewCount; + } } - } else if ( *( surfaceType_t * )( surf->data ) != SF_GRID ) { + } + else if (*(surfaceType_t*)(surf->data) != SF_GRID && *(surfaceType_t*)(surf->data) != SF_TRIANGLES) { surf->viewCount = tr.viewCount; + } // check the viewCount because the surface may have // already been added if it spans multiple leafs - if ( surf->viewCount != tr.viewCount ) { + if (surf->viewCount != tr.viewCount) { surf->viewCount = tr.viewCount; - list[*listlength] = (surfaceType_t *) surf->data; - ( *listlength )++; + list[*listlength] = (surfaceType_t*)surf->data; + (*listlength)++; } mark++; } @@ -215,35 +225,35 @@ R_AddMarkFragments ================= */ -void R_AddMarkFragments( int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY], - int numPlanes, vec3_t *normals, float *dists, - int maxPoints, vec3_t pointBuffer, - int maxFragments, markFragment_t *fragmentBuffer, - int *returnedPoints, int *returnedFragments, - vec3_t mins, vec3_t maxs ) { +void R_AddMarkFragments(int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_POLY], + int numPlanes, vec3_t* normals, float* dists, + int maxPoints, vec3_t pointBuffer, + int maxFragments, markFragment_t* fragmentBuffer, + int* returnedPoints, int* returnedFragments, + vec3_t mins, vec3_t maxs) { int pingPong, i; - markFragment_t *mf; + markFragment_t* mf; // chop the surface by all the bounding planes of the to be projected polygon pingPong = 0; - for ( i = 0 ; i < numPlanes ; i++ ) { + for (i = 0; i < numPlanes; i++) { - R_ChopPolyBehindPlane( numClipPoints, clipPoints[pingPong], - &numClipPoints, clipPoints[!pingPong], - normals[i], dists[i], 0.5 ); + R_ChopPolyBehindPlane(numClipPoints, clipPoints[pingPong], + &numClipPoints, clipPoints[!pingPong], + normals[i], dists[i], 0.5); pingPong ^= 1; - if ( numClipPoints == 0 ) { + if (numClipPoints == 0) { break; } } // completely clipped away? - if ( numClipPoints == 0 ) { + if (numClipPoints == 0) { return; } // add this fragment to the returned list - if ( numClipPoints + ( *returnedPoints ) > maxPoints ) { + if (numClipPoints + (*returnedPoints) > maxPoints) { return; // not enough space for this polygon } /* @@ -259,16 +269,16 @@ void R_AddMarkFragments( int numClipPoints, vec3_t clipPoints[2][MAX_VERTS_ON_PO if (i < numClipPoints) return; */ - mf = fragmentBuffer + ( *returnedFragments ); - mf->firstPoint = ( *returnedPoints ); + mf = fragmentBuffer + (*returnedFragments); + mf->firstPoint = (*returnedPoints); mf->numPoints = numClipPoints; //memcpy( pointBuffer + (*returnedPoints) * 3, clipPoints[pingPong], numClipPoints * sizeof(vec3_t) ); - for ( i = 0; i < numClipPoints; i++ ) { - VectorCopy( clipPoints[pingPong][i], (float *)pointBuffer + 5 * ( *returnedPoints + i ) ); + for (i = 0; i < numClipPoints; i++) { + VectorCopy(clipPoints[pingPong][i], (float*)pointBuffer + 5 * (*returnedPoints + i)); } - ( *returnedPoints ) += numClipPoints; - ( *returnedFragments )++; + (*returnedPoints) += numClipPoints; + (*returnedFragments)++; } /* @@ -277,11 +287,11 @@ R_OldMarkFragments ================= */ -int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projection, - int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) { +int R_OldMarkFragments(int numPoints, const vec3_t* points, const vec3_t projection, + int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer) { int numsurfaces, numPlanes; int i, j, k, m, n; - surfaceType_t *surfaces[64]; + surfaceType_t* surfaces[64]; vec3_t mins, maxs; int returnedFragments; int returnedPoints; @@ -289,68 +299,68 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec float dists[MAX_VERTS_ON_POLY + 2]; vec3_t clipPoints[2][MAX_VERTS_ON_POLY]; int numClipPoints; - float *v; - srfSurfaceFace_t *surf; - srfGridMesh_t *cv; - drawVert_t *dv; + float* v; + srfSurfaceFace_t* surf; + srfGridMesh_t* cv; + drawVert_t* dv; vec3_t normal; vec3_t projectionDir; vec3_t v1, v2; - int *indexes; + int* indexes; //increment view count for double check prevention tr.viewCount++; // - VectorNormalize2( projection, projectionDir ); + VectorNormalize2(projection, projectionDir); // find all the brushes that are to be considered - ClearBounds( mins, maxs ); - for ( i = 0 ; i < numPoints ; i++ ) { + ClearBounds(mins, maxs); + for (i = 0; i < numPoints; i++) { vec3_t temp; - AddPointToBounds( points[i], mins, maxs ); - VectorAdd( points[i], projection, temp ); - AddPointToBounds( temp, mins, maxs ); + AddPointToBounds(points[i], mins, maxs); + VectorAdd(points[i], projection, temp); + AddPointToBounds(temp, mins, maxs); // make sure we get all the leafs (also the one(s) in front of the hit surface) - VectorMA( points[i], -20, projectionDir, temp ); - AddPointToBounds( temp, mins, maxs ); + VectorMA(points[i], -20, projectionDir, temp); + AddPointToBounds(temp, mins, maxs); } - if ( numPoints > MAX_VERTS_ON_POLY ) { + if (numPoints > MAX_VERTS_ON_POLY) { numPoints = MAX_VERTS_ON_POLY; } // create the bounding planes for the to be projected polygon - for ( i = 0 ; i < numPoints ; i++ ) { - VectorSubtract( points[( i + 1 ) % numPoints], points[i], v1 ); - VectorAdd( points[i], projection, v2 ); - VectorSubtract( points[i], v2, v2 ); - CrossProduct( v1, v2, normals[i] ); - VectorNormalizeFast( normals[i] ); - dists[i] = DotProduct( normals[i], points[i] ); + for (i = 0; i < numPoints; i++) { + VectorSubtract(points[(i + 1) % numPoints], points[i], v1); + VectorAdd(points[i], projection, v2); + VectorSubtract(points[i], v2, v2); + CrossProduct(v1, v2, normals[i]); + VectorNormalizeFast(normals[i]); + dists[i] = DotProduct(normals[i], points[i]); } // add near and far clipping planes for projection - VectorCopy( projectionDir, normals[numPoints] ); - dists[numPoints] = DotProduct( normals[numPoints], points[0] ) - 32; - VectorCopy( projectionDir, normals[numPoints + 1] ); - VectorInverse( normals[numPoints + 1] ); - dists[numPoints + 1] = DotProduct( normals[numPoints + 1], points[0] ) - 20; + VectorCopy(projectionDir, normals[numPoints]); + dists[numPoints] = DotProduct(normals[numPoints], points[0]) - 32; + VectorCopy(projectionDir, normals[numPoints + 1]); + VectorInverse(normals[numPoints + 1]); + dists[numPoints + 1] = DotProduct(normals[numPoints + 1], points[0]) - 20; numPlanes = numPoints + 2; numsurfaces = 0; - R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir ); + R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 64, &numsurfaces, projectionDir); //assert(numsurfaces <= 64); //assert(numsurfaces != 64); returnedPoints = 0; returnedFragments = 0; - for ( i = 0 ; i < numsurfaces ; i++ ) { + for (i = 0; i < numsurfaces; i++) { - if ( *surfaces[i] == SF_GRID ) { + if (*surfaces[i] == SF_GRID) { - cv = (srfGridMesh_t *) surfaces[i]; - for ( m = 0 ; m < cv->height - 1 ; m++ ) { - for ( n = 0 ; n < cv->width - 1 ; n++ ) { + cv = (srfGridMesh_t*)surfaces[i]; + for (m = 0; m < cv->height - 1; m++) { + for (n = 0; n < cv->width - 1; n++) { // We triangulate the grid and chop all triangles within // the bounding planes of the to be projected polygon. // LOD is not taken into account, not such a big deal though. @@ -376,60 +386,61 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec dv = cv->verts + m * cv->width + n; - VectorCopy( dv[0].xyz, clipPoints[0][0] ); - VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0] ); - VectorCopy( dv[cv->width].xyz, clipPoints[0][1] ); - VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] ); - VectorCopy( dv[1].xyz, clipPoints[0][2] ); - VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2] ); + VectorCopy(dv[0].xyz, clipPoints[0][0]); + VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]); + VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); + VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); + VectorCopy(dv[1].xyz, clipPoints[0][2]); + VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]); // check the normal of this triangle - VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 ); - VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 ); - CrossProduct( v1, v2, normal ); - VectorNormalizeFast( normal ); - if ( DotProduct( normal, projectionDir ) < -0.1 ) { + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalizeFast(normal); + if (DotProduct(normal, projectionDir) < -0.1) { // add the fragments of this triangle - R_AddMarkFragments( numClipPoints, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); + R_AddMarkFragments(numClipPoints, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); - if ( returnedFragments == maxFragments ) { + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } - VectorCopy( dv[1].xyz, clipPoints[0][0] ); - VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0] ); - VectorCopy( dv[cv->width].xyz, clipPoints[0][1] ); - VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] ); - VectorCopy( dv[cv->width + 1].xyz, clipPoints[0][2] ); - VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2] ); + VectorCopy(dv[1].xyz, clipPoints[0][0]); + VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]); + VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); + VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); + VectorCopy(dv[cv->width + 1].xyz, clipPoints[0][2]); + VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2]); // check the normal of this triangle - VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 ); - VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 ); - CrossProduct( v1, v2, normal ); - VectorNormalizeFast( normal ); - if ( DotProduct( normal, projectionDir ) < -0.05 ) { + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalizeFast(normal); + if (DotProduct(normal, projectionDir) < -0.05) { // add the fragments of this triangle - R_AddMarkFragments( numClipPoints, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); + R_AddMarkFragments(numClipPoints, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); - if ( returnedFragments == maxFragments ) { + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } } } - } else if ( *surfaces[i] == SF_FACE ) { + } + else if (*surfaces[i] == SF_FACE) { - surf = ( srfSurfaceFace_t * ) surfaces[i]; + surf = (srfSurfaceFace_t*)surfaces[i]; // check the normal of this face - if ( DotProduct( surf->plane.normal, projectionDir ) > -0.5 ) { + if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { continue; } @@ -440,24 +451,80 @@ int R_OldMarkFragments( int numPoints, const vec3_t *points, const vec3_t projec VectorNormalize(normal); if (DotProduct(normal, projectionDir) > -0.5) continue; */ - indexes = ( int * )( (byte *)surf + surf->ofsIndices ); - for ( k = 0 ; k < surf->numIndices ; k += 3 ) { - for ( j = 0 ; j < 3 ; j++ ) { + indexes = (int*)((byte*)surf + surf->ofsIndices); + for (k = 0; k < surf->numIndices; k += 3) { + for (j = 0; j < 3; j++) { v = surf->points[0] + VERTEXSIZE * indexes[k + j];; - VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] ); + VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } + continue; + } + // Arnout: projection on models (mainly for terrain though) + else if (*surfaces[i] == SF_TRIANGLES) { + +#if 0 + srfTriangles2_t* cts; + cts = (srfTriangles2_t*)surfaces[i]; + + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } + continue; +#else + srfTriangles_t* cts; + cts = (srfTriangles_t*)surfaces[i]; + + /* + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalize(normal); + if (DotProduct(normal, projectionDir) > -0.5) continue; + */ + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + v = cts->verts[indexes[k + j]].xyz; + VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]); } // add the fragments of this face - R_AddMarkFragments( 3, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); - if ( returnedFragments == maxFragments ) { + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } continue; - } else { +#endif + } + else { // ignore all other world surfaces // might be cool to also project polygons on a triangle soup // however this will probably create huge amounts of extra polys @@ -474,11 +541,11 @@ R_MarkFragments ================= */ -int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t projection, - int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ) { +int R_MarkFragments(int orientation, const vec3_t* points, const vec3_t projection, + int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t* fragmentBuffer) { int numsurfaces, numPlanes; int i, j, k, m, n; - surfaceType_t *surfaces[4096]; + surfaceType_t* surfaces[4096]; vec3_t mins, maxs; int returnedFragments; int returnedPoints; @@ -486,14 +553,14 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project float dists[MAX_VERTS_ON_POLY + 2]; vec3_t clipPoints[2][MAX_VERTS_ON_POLY]; int numClipPoints; - float *v; - srfSurfaceFace_t *surf; - srfGridMesh_t *cv; - drawVert_t *dv; + float* v; + srfSurfaceFace_t* surf; + srfGridMesh_t* cv; + drawVert_t* dv; vec3_t normal; vec3_t projectionDir; vec3_t v1, v2; - int *indexes; + int* indexes; float radius; vec3_t center; // center of original mark //vec3_t bestCenter; // center point projected onto the closest surface @@ -506,56 +573,56 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project tr.viewCount++; // RF, negative maxFragments means we want original mapping - if ( maxFragments < 0 ) { + if (maxFragments < 0) { maxFragments = -maxFragments; //return R_OldMarkFragments( numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer ); oldMapping = qtrue; } - VectorClear( center ); - for ( i = 0 ; i < numPoints ; i++ ) { - VectorAdd( points[i], center, center ); + VectorClear(center); + for (i = 0; i < numPoints; i++) { + VectorAdd(points[i], center, center); } - VectorScale( center, 1.0 / numPoints, center ); + VectorScale(center, 1.0 / numPoints, center); // - radius = VectorNormalize2( projection, projectionDir ) / 2.0; + radius = VectorNormalize2(projection, projectionDir) / 2.0; bestdist = 0; - VectorNegate( projectionDir, bestnormal ); + VectorNegate(projectionDir, bestnormal); // find all the brushes that are to be considered - ClearBounds( mins, maxs ); - for ( i = 0 ; i < numPoints ; i++ ) { + ClearBounds(mins, maxs); + for (i = 0; i < numPoints; i++) { vec3_t temp; - AddPointToBounds( points[i], mins, maxs ); - VectorMA( points[i], 1 * ( 1 + oldMapping * radius * 4 ), projection, temp ); - AddPointToBounds( temp, mins, maxs ); + AddPointToBounds(points[i], mins, maxs); + VectorMA(points[i], 1 * (1 + oldMapping * radius * 4), projection, temp); + AddPointToBounds(temp, mins, maxs); // make sure we get all the leafs (also the one(s) in front of the hit surface) - VectorMA( points[i], -20 * ( 1.0 + (float)oldMapping * ( radius / 20.0 ) * 4 ), projectionDir, temp ); - AddPointToBounds( temp, mins, maxs ); + VectorMA(points[i], -20 * (1.0 + (float)oldMapping * (radius / 20.0) * 4), projectionDir, temp); + AddPointToBounds(temp, mins, maxs); } - if ( numPoints > MAX_VERTS_ON_POLY ) { + if (numPoints > MAX_VERTS_ON_POLY) { numPoints = MAX_VERTS_ON_POLY; } // create the bounding planes for the to be projected polygon - for ( i = 0 ; i < numPoints ; i++ ) { - VectorSubtract( points[( i + 1 ) % numPoints], points[i], v1 ); - VectorAdd( points[i], projection, v2 ); - VectorSubtract( points[i], v2, v2 ); - CrossProduct( v1, v2, normals[i] ); - VectorNormalize( normals[i] ); - dists[i] = DotProduct( normals[i], points[i] ); + for (i = 0; i < numPoints; i++) { + VectorSubtract(points[(i + 1) % numPoints], points[i], v1); + VectorAdd(points[i], projection, v2); + VectorSubtract(points[i], v2, v2); + CrossProduct(v1, v2, normals[i]); + VectorNormalize(normals[i]); + dists[i] = DotProduct(normals[i], points[i]); } // add near and far clipping planes for projection - VectorCopy( projectionDir, normals[numPoints] ); - dists[numPoints] = DotProduct( normals[numPoints], points[0] ) - radius * ( 1 + oldMapping * 10 ); - VectorCopy( projectionDir, normals[numPoints + 1] ); - VectorInverse( normals[numPoints + 1] ); - dists[numPoints + 1] = DotProduct( normals[numPoints + 1], points[0] ) - radius * ( 1 + oldMapping * 10 ); + VectorCopy(projectionDir, normals[numPoints]); + dists[numPoints] = DotProduct(normals[numPoints], points[0]) - radius * (1 + oldMapping * 10); + VectorCopy(projectionDir, normals[numPoints + 1]); + VectorInverse(normals[numPoints + 1]); + dists[numPoints + 1] = DotProduct(normals[numPoints + 1], points[0]) - radius * (1 + oldMapping * 10); numPlanes = numPoints + 2; numsurfaces = 0; - R_BoxSurfaces_r( tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir ); + R_BoxSurfaces_r(tr.world->nodes, mins, maxs, surfaces, 4096, &numsurfaces, projectionDir); //assert(numsurfaces <= 64); //assert(numsurfaces != 64); @@ -565,42 +632,42 @@ int R_MarkFragments( int orientation, const vec3_t *points, const vec3_t project returnedFragments = 0; // find the closest surface to center the decal there, and wrap around other surfaces - if ( !oldMapping ) { -/* + if (!oldMapping) { + /* for ( i = 0 ; i < numsurfaces ; i++ ) { - if (*surfaces[i] == SF_FACE) { - surf = ( srfSurfaceFace_t * ) surfaces[i]; - // Ridah, check if this is the closest surface - dot = DotProduct( center, surf->plane.normal ); - dot -= surf->plane.dist; - if (!bestdist) { - if (dot < 0) - bestdist = fabs(dot) + 1000; // avoid this surface, since the point is behind it - else - bestdist = dot; - VectorCopy( surf->plane.normal, bestnormal ); - VectorMA( center, -dot, surf->plane.normal, bestCenter ); - } else if (dot >= 0 && dot < bestdist) { - bestdist = dot; - VectorCopy( surf->plane.normal, bestnormal ); - VectorMA( center, -dot, surf->plane.normal, bestCenter ); - } - } + if (*surfaces[i] == SF_FACE) { + surf = ( srfSurfaceFace_t * ) surfaces[i]; + // Ridah, check if this is the closest surface + dot = DotProduct( center, surf->plane.normal ); + dot -= surf->plane.dist; + if (!bestdist) { + if (dot < 0) + bestdist = fabs(dot) + 1000; // avoid this surface, since the point is behind it + else + bestdist = dot; + VectorCopy( surf->plane.normal, bestnormal ); + VectorMA( center, -dot, surf->plane.normal, bestCenter ); + } else if (dot >= 0 && dot < bestdist) { + bestdist = dot; + VectorCopy( surf->plane.normal, bestnormal ); + VectorMA( center, -dot, surf->plane.normal, bestCenter ); + } + } } // bestCenter is now the real center VectorCopy( bestCenter, center ); -Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bestnormal[2] ); -*/ - VectorNegate( bestnormal, bestnormal ); + Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bestnormal[2] ); + */ + VectorNegate(bestnormal, bestnormal); } - for ( i = 0 ; i < numsurfaces ; i++ ) { + for (i = 0; i < numsurfaces; i++) { - if ( *surfaces[i] == SF_GRID ) { + if (*surfaces[i] == SF_GRID) { - cv = (srfGridMesh_t *) surfaces[i]; - for ( m = 0 ; m < cv->height - 1 ; m++ ) { - for ( n = 0 ; n < cv->width - 1 ; n++ ) { + cv = (srfGridMesh_t*)surfaces[i]; + for (m = 0; m < cv->height - 1; m++) { + for (n = 0; n < cv->width - 1; n++) { // We triangulate the grid and chop all triangles within // the bounding planes of the to be projected polygon. // LOD is not taken into account, not such a big deal though. @@ -626,57 +693,58 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes dv = cv->verts + m * cv->width + n; - VectorCopy( dv[0].xyz, clipPoints[0][0] ); - VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0] ); - VectorCopy( dv[cv->width].xyz, clipPoints[0][1] ); - VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] ); - VectorCopy( dv[1].xyz, clipPoints[0][2] ); - VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2] ); + VectorCopy(dv[0].xyz, clipPoints[0][0]); + VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[0].normal, clipPoints[0][0]); + VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); + VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); + VectorCopy(dv[1].xyz, clipPoints[0][2]); + VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[1].normal, clipPoints[0][2]); // check the normal of this triangle - VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 ); - VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 ); - CrossProduct( v1, v2, normal ); - VectorNormalize( normal ); - if ( DotProduct( normal, projectionDir ) < -0.1 ) { + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalize(normal); + if (DotProduct(normal, projectionDir) < -0.1) { // add the fragments of this triangle - R_AddMarkFragments( numClipPoints, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); + R_AddMarkFragments(numClipPoints, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); - if ( returnedFragments == maxFragments ) { + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } - VectorCopy( dv[1].xyz, clipPoints[0][0] ); - VectorMA( clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0] ); - VectorCopy( dv[cv->width].xyz, clipPoints[0][1] ); - VectorMA( clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1] ); - VectorCopy( dv[cv->width + 1].xyz, clipPoints[0][2] ); - VectorMA( clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2] ); + VectorCopy(dv[1].xyz, clipPoints[0][0]); + VectorMA(clipPoints[0][0], MARKER_OFFSET, dv[1].normal, clipPoints[0][0]); + VectorCopy(dv[cv->width].xyz, clipPoints[0][1]); + VectorMA(clipPoints[0][1], MARKER_OFFSET, dv[cv->width].normal, clipPoints[0][1]); + VectorCopy(dv[cv->width + 1].xyz, clipPoints[0][2]); + VectorMA(clipPoints[0][2], MARKER_OFFSET, dv[cv->width + 1].normal, clipPoints[0][2]); // check the normal of this triangle - VectorSubtract( clipPoints[0][0], clipPoints[0][1], v1 ); - VectorSubtract( clipPoints[0][2], clipPoints[0][1], v2 ); - CrossProduct( v1, v2, normal ); - VectorNormalize( normal ); - if ( DotProduct( normal, projectionDir ) < -0.05 ) { + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalize(normal); + if (DotProduct(normal, projectionDir) < -0.05) { // add the fragments of this triangle - R_AddMarkFragments( numClipPoints, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); + R_AddMarkFragments(numClipPoints, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); - if ( returnedFragments == maxFragments ) { + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } } } - } else if ( *surfaces[i] == SF_FACE ) { - extern float VectorDistance( vec3_t v1, vec3_t v2 ); + } + else if (*surfaces[i] == SF_FACE) { + extern float VectorDistance(vec3_t v1, vec3_t v2); vec3_t axis[3]; float texCoordScale, dot; vec3_t originalPoints[4]; @@ -687,129 +755,297 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes vec3_t lnormals[MAX_VERTS_ON_POLY + 2]; float ldists[MAX_VERTS_ON_POLY + 2]; vec3_t lmins, lmaxs; + vec3_t surfnormal; - surf = ( srfSurfaceFace_t * ) surfaces[i]; + surf = (srfSurfaceFace_t*)surfaces[i]; + + if (surf->plane.type == PLANE_NON_PLANAR) { + VectorCopy(bestnormal, surfnormal); + } + else { + VectorCopy(surf->plane.normal, surfnormal); + } - if ( !oldMapping ) { + if (!oldMapping) { // Ridah, create a new clip box such that this decal surface is mapped onto // the current surface without distortion. To find the center of the new clip box, // we project the center of the original impact center out along the projection vector, // onto the current surface - // find the center of the new decal - dot = DotProduct( center, surf->plane.normal ); - dot -= surf->plane.dist; - // check the normal of this face - if ( dot < -epsilon && DotProduct( surf->plane.normal, projectionDir ) >= 0.01 ) { - continue; - } else if ( fabs( dot ) > radius ) { - continue; + if (surf->plane.type == PLANE_NON_PLANAR) { + VectorCopy(center, newCenter); + } + else { + // find the center of the new decal + dot = DotProduct(center, surfnormal); + dot -= surf->plane.dist; + // check the normal of this face + if (dot < -epsilon && DotProduct(surfnormal, projectionDir) >= 0.01) { + continue; + } + else if (fabs(dot) > radius) { + continue; + } + // if the impact point is behind the surface, subtract the projection, otherwise add it + VectorMA(center, -dot, bestnormal, newCenter); } - // if the impact point is behind the surface, subtract the projection, otherwise add it - VectorMA( center, -dot, bestnormal, newCenter ); // recalc dot from the offset position - dot = DotProduct( newCenter, surf->plane.normal ); + dot = DotProduct(newCenter, surfnormal); dot -= surf->plane.dist; - VectorMA( newCenter, -dot, surf->plane.normal, newCenter ); + VectorMA(newCenter, -dot, surfnormal, newCenter); - VectorMA( newCenter, MARKER_OFFSET, surf->plane.normal, newCenter ); + VectorMA(newCenter, MARKER_OFFSET, surfnormal, newCenter); // create the texture axis - VectorNormalize2( surf->plane.normal, axis[0] ); - PerpendicularVector( axis[1], axis[0] ); - RotatePointAroundVector( axis[2], axis[0], axis[1], (float)orientation ); - CrossProduct( axis[0], axis[2], axis[1] ); + VectorNormalize2(surfnormal, axis[0]); + PerpendicularVector(axis[1], axis[0]); + RotatePointAroundVector(axis[2], axis[0], axis[1], (float)orientation); + CrossProduct(axis[0], axis[2], axis[1]); texCoordScale = 0.5 * 1.0 / radius; // create the full polygon - for ( j = 0 ; j < 3 ; j++ ) { + for (j = 0; j < 3; j++) { originalPoints[0][j] = newCenter[j] - radius * axis[1][j] - radius * axis[2][j]; originalPoints[1][j] = newCenter[j] + radius * axis[1][j] - radius * axis[2][j]; originalPoints[2][j] = newCenter[j] + radius * axis[1][j] + radius * axis[2][j]; originalPoints[3][j] = newCenter[j] - radius * axis[1][j] + radius * axis[2][j]; } - ClearBounds( lmins, lmaxs ); + ClearBounds(lmins, lmaxs); // create the bounding planes for the to be projected polygon - for ( j = 0 ; j < 4 ; j++ ) { - AddPointToBounds( originalPoints[j], lmins, lmaxs ); - - VectorSubtract( originalPoints[( j + 1 ) % numPoints], originalPoints[j], v1 ); - VectorSubtract( originalPoints[j], surf->plane.normal, v2 ); - VectorSubtract( originalPoints[j], v2, v2 ); - CrossProduct( v1, v2, lnormals[j] ); - VectorNormalize( lnormals[j] ); - ldists[j] = DotProduct( lnormals[j], originalPoints[j] ); + for (j = 0; j < 4; j++) { + AddPointToBounds(originalPoints[j], lmins, lmaxs); + + VectorSubtract(originalPoints[(j + 1) % numPoints], originalPoints[j], v1); + VectorSubtract(originalPoints[j], surfnormal, v2); + VectorSubtract(originalPoints[j], v2, v2); + CrossProduct(v1, v2, lnormals[j]); + VectorNormalize(lnormals[j]); + ldists[j] = DotProduct(lnormals[j], originalPoints[j]); } numPlanes = numPoints; // done. - indexes = ( int * )( (byte *)surf + surf->ofsIndices ); - for ( k = 0 ; k < surf->numIndices ; k += 3 ) { - for ( j = 0 ; j < 3 ; j++ ) { + indexes = (int*)((byte*)surf + surf->ofsIndices); + for (k = 0; k < surf->numIndices; k += 3) { + for (j = 0; j < 3; j++) { v = surf->points[0] + VERTEXSIZE * indexes[k + j]; - VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] ); + VectorMA(v, MARKER_OFFSET, surfnormal, clipPoints[0][j]); } oldNumPoints = returnedPoints; // add the fragments of this face - R_AddMarkFragments( 3, clipPoints, - numPlanes, lnormals, ldists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, lmins, lmaxs ); + R_AddMarkFragments(3, clipPoints, + numPlanes, lnormals, ldists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, lmins, lmaxs); - if ( oldNumPoints != returnedPoints ) { + if (oldNumPoints != returnedPoints) { // flag this surface as already having computed ST's fragmentBuffer[returnedFragments - 1].numPoints *= -1; // Ridah, calculate ST's - for ( j = 0 ; j < ( returnedPoints - oldNumPoints ) ; j++ ) { - VectorSubtract( (float *)pointBuffer + 5 * ( oldNumPoints + j ), newCenter, delta ); - *( (float *)pointBuffer + 5 * ( oldNumPoints + j ) + 3 ) = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale; - *( (float *)pointBuffer + 5 * ( oldNumPoints + j ) + 4 ) = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale; + for (j = 0; j < (returnedPoints - oldNumPoints); j++) { + VectorSubtract((float*)pointBuffer + 5 * (oldNumPoints + j), newCenter, delta); + *((float*)pointBuffer + 5 * (oldNumPoints + j) + 3) = 0.5 + DotProduct(delta, axis[1]) * texCoordScale; + *((float*)pointBuffer + 5 * (oldNumPoints + j) + 4) = 0.5 + DotProduct(delta, axis[2]) * texCoordScale; } } - if ( returnedFragments == maxFragments ) { + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } - } else { // old mapping + } + else { // old mapping // check the normal of this face + // Arnout: wolf code was disabled, but differs from q3 code (maybe wolf one was broken and fixed in q3?): + /* if (DotProduct(surf->plane.normal, projectionDir) > -0.5) { + continue; + }*/ + + // Wolf code: //if (DotProduct(surf->plane.normal, projectionDir) > 0.0) { // continue; //} - indexes = ( int * )( (byte *)surf + surf->ofsIndices ); - for ( k = 0 ; k < surf->numIndices ; k += 3 ) { - for ( j = 0 ; j < 3 ; j++ ) { + indexes = (int*)((byte*)surf + surf->ofsIndices); + for (k = 0; k < surf->numIndices; k += 3) { + for (j = 0; j < 3; j++) { v = surf->points[0] + VERTEXSIZE * indexes[k + j];; - VectorMA( v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j] ); + VectorMA(v, MARKER_OFFSET, surf->plane.normal, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } + } + + continue; + } + // Arnout: projection on models (mainly for terrain though) + else if (*surfaces[i] == SF_TRIANGLES) { + +#if 0 + // duplicated so we don't mess with the original clips for the curved surfaces + vec3_t lnormals[MAX_VERTS_ON_POLY + 2]; + float ldists[MAX_VERTS_ON_POLY + 2]; + + srfTriangles2_t* cts; + cts = (srfTriangles2_t*)surfaces[i]; + if (!oldMapping) { + for (k = 0; k < numPoints; k++) { + VectorNegate(normals[k], lnormals[k]); + ldists[k] = -dists[k]; + } + VectorNegate(normals[numPoints], lnormals[numPoints]); + ldists[numPoints] = dists[numPoints + 1]; + VectorNegate(normals[numPoints + 1], lnormals[numPoints + 1]); + ldists[numPoints + 1] = dists[numPoints]; + + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, lnormals, ldists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } + } + else { + + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + VectorMA(cts->xyz[indexes[k + j]].v, MARKER_OFFSET, cts->normal[indexes[k + j]].v, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } + } + + continue; +#else + // duplicated so we don't mess with the original clips for the curved surfaces + vec3_t lnormals[MAX_VERTS_ON_POLY + 2]; + float ldists[MAX_VERTS_ON_POLY + 2]; + //vec3_t lprojection, lprojectionDir; + + srfTriangles_t* cts; + cts = (srfTriangles_t*)surfaces[i]; + if (!oldMapping) { + /*VectorNegate( projection, lprojection ); + VectorNormalize2( lprojection, lprojectionDir ); + + radius = VectorNormalize2( lprojection, lprojectionDir ) / 2.0; + + // create the bounding planes for the to be projected polygon + for ( k = 0 ; k < numPoints ; k++ ) { + VectorSubtract(points[(k+1)%numPoints], points[k], v1); + VectorAdd(points[k], lprojection, v2); + VectorSubtract(points[k], v2, v2); + CrossProduct(v1, v2, lnormals[k]); + VectorNormalizeFast(lnormals[k]); + ldists[k] = DotProduct(lnormals[k], points[k]); + } + + // add near and far clipping planes for projection + VectorCopy(lprojectionDir, lnormals[numPoints]); + ldists[numPoints] = DotProduct(lnormals[numPoints], points[0]) - radius; + VectorCopy(lprojectionDir, lnormals[numPoints+1]); + VectorInverse(lnormals[numPoints+1]); + ldists[numPoints+1] = DotProduct(lnormals[numPoints+1], points[0]) - radius;*/ + + for (k = 0; k < numPoints; k++) { + VectorNegate(normals[k], lnormals[k]); + ldists[k] = -dists[k]; + } + VectorNegate(normals[numPoints], lnormals[numPoints]); + ldists[numPoints] = dists[numPoints + 1]; + VectorNegate(normals[numPoints + 1], lnormals[numPoints + 1]); + ldists[numPoints + 1] = dists[numPoints]; + + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + v = cts->verts[indexes[k + j]].xyz; + VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]); } // add the fragments of this face - R_AddMarkFragments( 3, clipPoints, - numPlanes, normals, dists, - maxPoints, pointBuffer, - maxFragments, fragmentBuffer, - &returnedPoints, &returnedFragments, mins, maxs ); - if ( returnedFragments == maxFragments ) { + R_AddMarkFragments(3, clipPoints, + numPlanes, lnormals, ldists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + + if (returnedFragments == maxFragments) { return returnedFragments; // not enough space for more fragments } } + } + else { + + /* + VectorSubtract(clipPoints[0][0], clipPoints[0][1], v1); + VectorSubtract(clipPoints[0][2], clipPoints[0][1], v2); + CrossProduct(v1, v2, normal); + VectorNormalize(normal); + if (DotProduct(normal, projectionDir) > -0.5) continue; + */ + indexes = cts->indexes; + for (k = 0; k < cts->numIndexes; k += 3) { + for (j = 0; j < 3; j++) { + v = cts->verts[indexes[k + j]].xyz; + VectorMA(v, MARKER_OFFSET, cts->verts[indexes[k + j]].normal, clipPoints[0][j]); + } + // add the fragments of this face + R_AddMarkFragments(3, clipPoints, + numPlanes, normals, dists, + maxPoints, pointBuffer, + maxFragments, fragmentBuffer, + &returnedPoints, &returnedFragments, mins, maxs); + if (returnedFragments == maxFragments) { + return returnedFragments; // not enough space for more fragments + } + } } continue; - } else { +#endif // 1 + } + else { // ignore all other world surfaces // might be cool to also project polygons on a triangle soup // however this will probably create huge amounts of extra polys @@ -819,4 +1055,3 @@ Com_Printf("bestnormal: %1.1f %1.1f %1.1f \n", bestnormal[0], bestnormal[1], bes } return returnedFragments; } - diff --git a/src/renderer/tr_shade.c b/src/renderer/tr_shade.c index 6a291fbb..8e84350b 100644 --- a/src/renderer/tr_shade.c +++ b/src/renderer/tr_shade.c @@ -425,7 +425,7 @@ static void ProjectDlightTexture( void ) { float *texCoords; byte *colors; byte clipBits[SHADER_MAX_VERTEXES]; - MAC_STATIC float texCoordsArray[SHADER_MAX_VERTEXES][2]; + float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; unsigned hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; @@ -676,7 +676,13 @@ static void RB_FogPass( void ) { fog_t *fog; int i; - if ( tr.refdef.rdflags & RDF_SNOOPERVIEW ) { // no fog pass in snooper + // no fog pass in snooper + if (tr.refdef.rdflags & RDF_SNOOPERVIEW || tess.shader->noFog || !r_wolffog->integer) { + return; + } + + // ydnar: no world, no fogging + if (backEnd.refdef.rdflags & RDF_NOWORLDMODEL) { return; } @@ -1152,11 +1158,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { // // set state // - if ( pStage->bundle[0].vertexLightmap && ( ( r_vertexLight->integer && !r_uiFullScreen->integer ) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) { - GL_Bind( tr.whiteImage ); - } else { - R_BindAnimatedImage( &pStage->bundle[0] ); - } + R_BindAnimatedImage(&pStage->bundle[0]); // Ridah, per stage fogging (detail textures) if ( tess.shader->noFog && pStage->isFogged ) { @@ -1202,10 +1204,20 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) { tess.svars.colors[i][3] *= alphaval; } } - } else { - GL_State( pStage->stateBits ); } //----(SA) end + // ydnar: lightmap stages should be GL_ONE GL_ZERO so they can be seen + else if (r_lightmap->integer && (pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap)) { + unsigned int stateBits; + + + stateBits = (pStage->stateBits & ~(GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS)) | + (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO); + GL_State(stateBits); + } + else { + GL_State( pStage->stateBits ); + } // // draw diff --git a/src/renderer/tr_shade_calc.c b/src/renderer/tr_shade_calc.c index 26bdfdd2..f52fe18e 100644 --- a/src/renderer/tr_shade_calc.c +++ b/src/renderer/tr_shade_calc.c @@ -666,7 +666,7 @@ void RB_CalcColorFromEntity( unsigned char *dstColors ) { void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ) { int i; int *pColors = ( int * ) dstColors; - unsigned char invModulate[3]; + unsigned char invModulate[4]; // L0 - ioquake static buffer overflow fix. int c; if ( !backEnd.currentEntity ) { diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c index 2cd8c2c9..83fe6218 100644 --- a/src/renderer/tr_shader.c +++ b/src/renderer/tr_shader.c @@ -1150,23 +1150,29 @@ skyParms =============== */ static void ParseSkyParms( char **text ) { - char *token; - static char *suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; + char* token; + static char* suf[6] = {"rt", "bk", "lf", "ft", "up", "dn"}; char pathname[MAX_QPATH]; int i; // outerbox - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) { - ri.Printf( PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name ); + token = COM_ParseExt(text, qfalse); + if (token[0] == 0) { + ri.Printf(PRINT_WARNING, "WARNING: 'skyParms' missing parameter in shader '%s'\n", shader.name); return; } - if ( strcmp( token, "-" ) ) { - for ( i = 0 ; i < 6 ; i++ ) { - Com_sprintf( pathname, sizeof( pathname ), "%s_%s.tga" - , token, suf[i] ); - shader.sky.outerbox[i] = R_FindImageFile( ( char * ) pathname, qtrue, qtrue, GL_CLAMP ); - if ( !shader.sky.outerbox[i] ) { + if (strcmp(token, "-")) { + for (i = 0; i < 6; i++) { + Com_sprintf(pathname, sizeof(pathname), "%s_%s.tga" + , token, suf[i]); + // L0 - ioquake ATI skybox fix +#ifdef GL_CLAMP_TO_EDGE + shader.sky.outerbox[i] = R_FindImageFile((char*)pathname, qtrue, qtrue, GL_CLAMP_TO_EDGE); +#else + shader.sky.outerbox[i] = R_FindImageFile((char*)pathname, qtrue, qtrue, GL_CLAMP); +#endif + // End + if (!shader.sky.outerbox[i]) { shader.sky.outerbox[i] = tr.defaultImage; } } @@ -1390,6 +1396,10 @@ static qboolean ParseShader( char **text ) { } // stage definition else if ( token[0] == '{' ) { + if (s >= MAX_SHADER_STAGES) { + ri.Printf(PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name); + return qfalse; + } if ( !ParseStage( &stages[s], text ) ) { return qfalse; } @@ -1533,7 +1543,7 @@ static qboolean ParseShader( char **text ) { ri.Printf( PRINT_WARNING, "WARNING: missing shader name for 'sunshader'\n" ); continue; } - tr.sunShaderName = CopyString( token ); + tr.sunShaderName = "sun"; } //----(SA) added else if ( !Q_stricmp( token, "lightgridmulamb" ) ) { // ambient multiplier for lightgrid @@ -2340,7 +2350,7 @@ static shader_t *FinishShader( void ) { shader.numUnfoggedPasses = stage; // fogonly shaders don't have any normal passes - if ( stage == 0 ) { + if (stage == 0 && !shader.isSky) { shader.sort = SS_FOG; } @@ -2514,6 +2524,12 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag lightmapIndex = LIGHTMAP_BY_VERTEX; } + else if (lightmapIndex < LIGHTMAP_2D) { + // negative lightmap indexes cause stray pointers (think tr.lightmaps[lightmapIndex]) + ri.Printf(PRINT_WARNING, "WARNING: shader '%s' has invalid lightmap index of %d\n", name, lightmapIndex); + lightmapIndex = LIGHTMAP_BY_VERTEX; + } + COM_StripExtension2( name, strippedName, sizeof( strippedName ) ); hash = generateHashValue( strippedName ); @@ -2521,25 +2537,6 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag // // see if the shader is already loaded // -#if 1 - for ( sh = hashTable[hash]; sh; sh = sh->next ) { - // index by name - - // Ridah, modified this so we don't keep trying to load an invalid lightmap shader -/* - if ( sh->lightmapIndex == lightmapIndex && - !Q_stricmp(sh->name, strippedName)) { - // match found - return sh; - } -*/ - if ( ( ( sh->lightmapIndex == lightmapIndex ) || ( sh->lightmapIndex < 0 && lightmapIndex >= 0 ) ) && - !Q_stricmp( sh->name, strippedName ) ) { - // match found - return sh; - } - } -#else for ( sh = hashTable[hash]; sh; sh = sh->next ) { // NOTE: if there was no shader or image available with the name strippedName // then a default shader is created with lightmapIndex == LIGHTMAP_NONE, so we @@ -2551,7 +2548,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag return sh; } } -#endif + // make sure the render thread is stopped, because we are probably // going to have to upload an image @@ -2675,6 +2672,13 @@ qhandle_t RE_RegisterShaderFromImage( const char *name, int lightmapIndex, image hash = generateHashValue( name ); + // probably not necessary since this function + // only gets called from tr_font.c with lightmapIndex == LIGHTMAP_2D + // but better safe than sorry. + if (lightmapIndex >= tr.numLightmaps) { + lightmapIndex = LIGHTMAP_WHITEIMAGE; + } + // // see if the shader is already loaded // @@ -3113,7 +3117,16 @@ static void CreateInternalShaders( void ) { static void CreateExternalShaders( void ) { tr.projectionShadowShader = R_FindShader( "projectionShadow", LIGHTMAP_NONE, qtrue ); tr.flareShader = R_FindShader( "flareShader", LIGHTMAP_NONE, qtrue ); -// tr.sunShader = R_FindShader( "sun", LIGHTMAP_NONE, qtrue ); //----(SA) let sky shader set this + // Hack to make fogging work correctly on flares. Fog colors are calculated + // in tr_flare.c already. + if (!tr.flareShader->defaultShader) { + int index; + + for (index = 0; index < tr.flareShader->numUnfoggedPasses; index++) { + tr.flareShader->stages[index]->adjustColorsForFog = ACFF_NONE; + tr.flareShader->stages[index]->stateBits |= GLS_DEPTHTEST_DISABLE; + } + } tr.sunflareShader[0] = R_FindShader( "sunflare1", LIGHTMAP_NONE, qtrue ); tr.dlightShader = R_FindShader( "dlightshader", LIGHTMAP_NONE, qtrue ); } diff --git a/src/renderer/tr_shadows.c b/src/renderer/tr_shadows.c index 599b7067..eb28fc39 100644 --- a/src/renderer/tr_shadows.c +++ b/src/renderer/tr_shadows.c @@ -162,6 +162,7 @@ void RB_ShadowTessEnd( void ) { int i; int numTris; vec3_t lightDir; + GLboolean rgba[4]; // we can only do this if we have enough space in the vertex buffers if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { @@ -222,6 +223,7 @@ void RB_ShadowTessEnd( void ) { qglColor3f( 0.2f, 0.2f, 0.2f ); // don't write to the color buffer + qglGetBooleanv(GL_COLOR_WRITEMASK, rgba); qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); qglEnable( GL_STENCIL_TEST ); @@ -250,9 +252,8 @@ void RB_ShadowTessEnd( void ) { R_RenderShadowEdges(); } - // reenable writing to the color buffer - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + qglColorMask(rgba[0], rgba[1], rgba[2], rgba[3]); } diff --git a/src/renderer/tr_sky.c b/src/renderer/tr_sky.c index 91ce508f..889aa28c 100644 --- a/src/renderer/tr_sky.c +++ b/src/renderer/tr_sky.c @@ -576,6 +576,9 @@ static void FillCloudySkySide( const int mins[2], const int maxs[2], qboolean ad tHeight = maxs[1] - mins[1] + 1; sWidth = maxs[0] - mins[0] + 1; + // ydnar: overflow check + RB_CHECKOVERFLOW((maxs[0] - mins[0]) * (maxs[1] - mins[1]), (sWidth - 1) * (tHeight - 1) * 6); + for ( t = mins[1] + HALF_SKY_SUBDIVISIONS; t <= maxs[1] + HALF_SKY_SUBDIVISIONS; t++ ) { for ( s = mins[0] + HALF_SKY_SUBDIVISIONS; s <= maxs[0] + HALF_SKY_SUBDIVISIONS; s++ ) @@ -716,7 +719,6 @@ static void FillCloudBox( const shader_t *shader, int stage ) { ** R_BuildCloudData */ void R_BuildCloudData( shaderCommands_t *input ) { - int i; shader_t *shader; shader = input->shader; @@ -731,13 +733,19 @@ void R_BuildCloudData( shaderCommands_t *input ) { tess.numVertexes = 0; if ( input->shader->sky.cloudHeight ) { - for ( i = 0; i < MAX_SHADER_STAGES; i++ ) - { - if ( !tess.xstages[i] ) { + // ok, this is really wierd. it's iterating through shader stages here, + // which is unecessary for a multi-stage sky shader, as far as i can tell + // nuking this +#if 0 + for (i = 0; i < MAX_SHADER_STAGES; i++) { + if (!tess.xstages[i]) { break; } - FillCloudBox( input->shader, i ); + FillCloudBox(input->shader, i); } +#else + FillCloudBox(input->shader, 0); +#endif } } @@ -826,6 +834,7 @@ void RB_DrawSun( void ) { if ( !r_drawSun->integer ) { return; } + qglPushMatrix(); qglLoadMatrixf( backEnd.viewParms.world.modelMatrix ); qglTranslatef( backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2] ); @@ -850,58 +859,6 @@ void RB_DrawSun( void ) { RB_BeginSurface( tr.sunShader, tess.fogNum ); RB_AddQuadStamp( origin, vec1, vec2, color ); -/* - VectorCopy( origin, temp ); - VectorSubtract( temp, vec1, temp ); - VectorSubtract( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorAdd( temp, vec1, temp ); - VectorSubtract( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorAdd( temp, vec1, temp ); - VectorAdd( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 1; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - VectorCopy( origin, temp ); - VectorSubtract( temp, vec1, temp ); - VectorAdd( temp, vec2, temp ); - VectorCopy( temp, tess.xyz[tess.numVertexes] ); - tess.texCoords[tess.numVertexes][0][0] = 1; - tess.texCoords[tess.numVertexes][0][1] = 0; - tess.vertexColors[tess.numVertexes][0] = 255; - tess.vertexColors[tess.numVertexes][1] = 255; - tess.vertexColors[tess.numVertexes][2] = 255; - tess.numVertexes++; - - tess.indexes[tess.numIndexes++] = 0; - tess.indexes[tess.numIndexes++] = 1; - tess.indexes[tess.numIndexes++] = 2; - tess.indexes[tess.numIndexes++] = 0; - tess.indexes[tess.numIndexes++] = 2; - tess.indexes[tess.numIndexes++] = 3; -*/ RB_EndSurface(); @@ -936,12 +893,10 @@ void RB_DrawSun( void ) { // back to normal depth range qglDepthRange( 0.0, 1.0 ); + qglPopMatrix(); } - - extern void R_Fog( glfog_t *curfog ); - /* ================ RB_StageIteratorSky @@ -990,6 +945,8 @@ void RB_StageIteratorSky( void ) { qglDepthRange( 1.0, 1.0 ); } + GL_Cull(CT_TWO_SIDED); + // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); diff --git a/src/renderer/tr_surface.c b/src/renderer/tr_surface.c index b444798e..7e60e460 100644 --- a/src/renderer/tr_surface.c +++ b/src/renderer/tr_surface.c @@ -464,6 +464,14 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f vbase = tess.numVertexes; + // Gordon: configurable tile + if (backEnd.currentEntity->e.radius > 0) { + t = len / backEnd.currentEntity->e.radius; + } + else { + t = len / 256.f; + } + spanWidth2 = -spanWidth; // FIXME: use quad stamp? @@ -473,6 +481,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0] * 0.25; tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1] * 0.25; tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2] * 0.25; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3]; tess.numVertexes++; VectorMA( start, spanWidth2, up, tess.xyz[tess.numVertexes] ); @@ -481,6 +490,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3]; tess.numVertexes++; VectorMA( end, spanWidth, up, tess.xyz[tess.numVertexes] ); @@ -490,6 +500,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3]; tess.numVertexes++; VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); @@ -498,6 +509,7 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3]; tess.numVertexes++; tess.indexes[tess.numIndexes++] = vbase; @@ -626,7 +638,7 @@ void RB_SurfaceRailCore( void ) { CrossProduct( v1, v2, right ); VectorNormalize( right ); - DoRailCore( start, end, right, len, r_railCoreWidth->integer ); + DoRailCore(start, end, right, len, e->frame > 0?e->frame:1); } /* @@ -722,14 +734,12 @@ static void VectorArrayNormalize( vec4_t *normals, unsigned int count ) { } - - /* ** LerpMeshVertexes */ static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) { - short *oldXyz, *newXyz, *oldNormals, *newNormals; - float *outXyz, *outNormal; + short* oldXyz, * newXyz, * oldNormals, * newNormals; + float* outXyz, * outNormal; float oldXyzScale, newXyzScale; float oldNormalScale, newNormalScale; int vertNum; @@ -739,57 +749,58 @@ static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) { outXyz = tess.xyz[tess.numVertexes]; outNormal = tess.normal[tess.numVertexes]; - newXyz = ( short * )( (byte *)surf + surf->ofsXyzNormals ) - + ( backEnd.currentEntity->e.frame * surf->numVerts * 4 ); + newXyz = (short*)((byte*)surf + surf->ofsXyzNormals) + + (backEnd.currentEntity->e.frame * surf->numVerts * 4); newNormals = newXyz + 3; - newXyzScale = MD3_XYZ_SCALE * ( 1.0 - backlerp ); + newXyzScale = MD3_XYZ_SCALE * (1.0 - backlerp); newNormalScale = 1.0 - backlerp; numVerts = surf->numVerts; - if ( backlerp == 0 ) { + if (backlerp == 0) { // // just copy the vertexes // - for ( vertNum = 0 ; vertNum < numVerts ; vertNum++, - newXyz += 4, newNormals += 4, - outXyz += 4, outNormal += 4 ) - { + for (vertNum = 0; vertNum < numVerts; vertNum++, + newXyz += 4, newNormals += 4, + outXyz += 4, outNormal += 4) { outXyz[0] = newXyz[0] * newXyzScale; outXyz[1] = newXyz[1] * newXyzScale; outXyz[2] = newXyz[2] * newXyzScale; - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - lat *= ( FUNCTABLE_SIZE / 256 ); - lng *= ( FUNCTABLE_SIZE / 256 ); + lat = (newNormals[0] >> 8) & 0xff; + lng = (newNormals[0] & 0xff); + lat *= (FUNCTABLE_SIZE / 256); + lng *= (FUNCTABLE_SIZE / 256); // decode X as cos( lat ) * sin( long ) // decode Y as sin( lat ) * sin( long ) // decode Z as cos( long ) - outNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; + outNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng]; outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - outNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK]; + outNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK]; } - } else { + } + else { // // interpolate and copy the vertex and normal // - oldXyz = ( short * )( (byte *)surf + surf->ofsXyzNormals ) - + ( backEnd.currentEntity->e.oldframe * surf->numVerts * 4 ); + oldXyz = (short*)((byte*)surf + surf->ofsXyzNormals) + + (backEnd.currentEntity->e.oldframe * surf->numVerts * 4); oldNormals = oldXyz + 3; oldXyzScale = MD3_XYZ_SCALE * backlerp; oldNormalScale = backlerp; - for ( vertNum = 0 ; vertNum < numVerts ; vertNum++, - oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, - outXyz += 4, outNormal += 4 ) - { + for (vertNum = 0; vertNum < numVerts; vertNum++, + oldXyz += 4, newXyz += 4, oldNormals += 4, newNormals += 4, + outXyz += 4, outNormal += 4) { +#if 0 vec3_t uncompressedOldNormal, uncompressedNewNormal; +#endif // interpolate the xyz outXyz[0] = oldXyz[0] * oldXyzScale + newXyz[0] * newXyzScale; @@ -797,30 +808,44 @@ static void LerpMeshVertexes( md3Surface_t *surf, float backlerp ) { outXyz[2] = oldXyz[2] * oldXyzScale + newXyz[2] * newXyzScale; // FIXME: interpolate lat/long instead? - lat = ( newNormals[0] >> 8 ) & 0xff; - lng = ( newNormals[0] & 0xff ); - lat *= 4; - lng *= 4; - uncompressedNewNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; + // ydnar: ok :) +#if 0 + lat = (newNormals[0] >> 8) & 0xff; + lng = (newNormals[0] & 0xff); + lat *= (FUNCTABLE_SIZE / 256); + lng *= (FUNCTABLE_SIZE / 256); + uncompressedNewNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng]; uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedNewNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK]; + uncompressedNewNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK]; - lat = ( oldNormals[0] >> 8 ) & 0xff; - lng = ( oldNormals[0] & 0xff ); - lat *= 4; - lng *= 4; + lat = (oldNormals[0] >> 8) & 0xff; + lng = (oldNormals[0] & 0xff); + lat *= (FUNCTABLE_SIZE / 256); + lng *= (FUNCTABLE_SIZE / 256); - uncompressedOldNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; + uncompressedOldNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng]; uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; - uncompressedOldNormal[2] = tr.sinTable[( lng + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK]; + uncompressedOldNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK]; outNormal[0] = uncompressedOldNormal[0] * oldNormalScale + uncompressedNewNormal[0] * newNormalScale; outNormal[1] = uncompressedOldNormal[1] * oldNormalScale + uncompressedNewNormal[1] * newNormalScale; outNormal[2] = uncompressedOldNormal[2] * oldNormalScale + uncompressedNewNormal[2] * newNormalScale; +#else + lat = myftol((((oldNormals[0] >> 8) & 0xFF) * (FUNCTABLE_SIZE / 256) * newNormalScale) + + (((oldNormals[0] >> 8) & 0xFF) * (FUNCTABLE_SIZE / 256) * oldNormalScale)); + lng = myftol(((oldNormals[0] & 0xFF) * (FUNCTABLE_SIZE / 256) * newNormalScale) + + ((oldNormals[0] & 0xFF) * (FUNCTABLE_SIZE / 256) * oldNormalScale)); -// VectorNormalize (outNormal); + outNormal[0] = tr.sinTable[(lat + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK] * tr.sinTable[lng]; + outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; + outNormal[2] = tr.sinTable[(lng + (FUNCTABLE_SIZE / 4)) & FUNCTABLE_MASK]; +#endif + + // VectorNormalize (outNormal); } - VectorArrayNormalize( (vec4_t *)tess.normal[tess.numVertexes], numVerts ); + + // ydnar: unecessary because of lat/lng lerping + //% VectorArrayNormalize((vec4_t *)tess.normal[tess.numVertexes].v, numVerts); } } @@ -960,8 +985,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) { } else { lat = ( newNormals[0] >> 8 ) & 0xff; lng = ( newNormals[0] & 0xff ); - lat *= 4; - lng *= 4; + lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh: + lng *= (FUNCTABLE_SIZE / 256); outNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; outNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; @@ -1007,8 +1032,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) { } else { lat = ( newNormals[0] >> 8 ) & 0xff; lng = ( newNormals[0] & 0xff ); - lat *= 4; - lng *= 4; + lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh: + lng *= (FUNCTABLE_SIZE / 256); uncompressedNewNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; uncompressedNewNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; @@ -1022,8 +1047,8 @@ static void LerpCMeshVertexes( mdcSurface_t *surf, float backlerp ) { } else { lat = ( oldNormals[0] >> 8 ) & 0xff; lng = ( oldNormals[0] & 0xff ); - lat *= 4; - lng *= 4; + lat *= (FUNCTABLE_SIZE / 256); // was 4 :sigh: + lng *= (FUNCTABLE_SIZE / 256); uncompressedOldNormal[0] = tr.sinTable[( lat + ( FUNCTABLE_SIZE / 4 ) ) & FUNCTABLE_MASK] * tr.sinTable[lng]; uncompressedOldNormal[1] = tr.sinTable[lat] * tr.sinTable[lng]; @@ -1155,9 +1180,9 @@ static float LodErrorForVolume( vec3_t local, float radius ) { vec3_t world; float d; - // never let it go negative - if ( r_lodCurveError->value < 0 ) { - return 0; + // never let it go lower than 1 + if (r_lodCurveError->value < 1) { + return 1; } world[0] = local[0] * backEnd.or.axis[0][0] + local[1] * backEnd.or.axis[1][0] + diff --git a/src/renderer/tr_world.c b/src/renderer/tr_world.c index 2d2120ae..e4a07776 100644 --- a/src/renderer/tr_world.c +++ b/src/renderer/tr_world.c @@ -141,19 +141,32 @@ static qboolean R_CullSurface( surfaceType_t *surface, shader_t *shader ) { } sface = ( srfSurfaceFace_t * ) surface; - d = DotProduct( tr.or.viewOrigin, sface->plane.normal ); - - // don't cull exactly on the plane, because there are levels of rounding - // through the BSP, ICD, and hardware that may cause pixel gaps if an - // epsilon isn't allowed here - if ( shader->cullType == CT_FRONT_SIDED ) { - if ( d < sface->plane.dist - 8 ) { - return qtrue; + // L0 - ET Port + // plane cull + if (sface->plane.type != PLANE_NON_PLANAR && r_facePlaneCull->integer) { + d = DotProduct(tr. or .viewOrigin, sface->plane.normal) - sface->plane.dist; + /* + if (d > 0.0f) { + *frontFace = 1; + } */ + + // don't cull exactly on the plane, because there are levels of rounding + // through the BSP, ICD, and hardware that may cause pixel gaps if an + // epsilon isn't allowed here + if (shader->cullType == CT_FRONT_SIDED) { + if (d < -8.0f) { + //tr.pc.c_plane_cull_out++; + return qtrue; + } } - } else { - if ( d > sface->plane.dist + 8 ) { - return qtrue; + else if (shader->cullType == CT_BACK_SIDED) { + if (d > 8.0f) { + //tr.pc.c_plane_cull_out++; + return qtrue; + } } + + //tr.pc.c_plane_cull_in++; } return qfalse; @@ -378,6 +391,7 @@ void R_AddBrushModelSurfaces( trRefEntity_t *ent ) { return; } + R_SetupEntityLighting(&tr.refdef, ent); R_DlightBmodel( bmodel ); //----(SA) modified