diff options
Diffstat (limited to 'src/renderer')
-rw-r--r-- | src/renderer/tr_backend.c | 103 | ||||
-rw-r--r-- | src/renderer/tr_bsp.c | 3 | ||||
-rw-r--r-- | src/renderer/tr_cmds.c | 139 | ||||
-rw-r--r-- | src/renderer/tr_image.c | 79 | ||||
-rw-r--r-- | src/renderer/tr_init.c | 45 | ||||
-rw-r--r-- | src/renderer/tr_local.h | 38 | ||||
-rw-r--r-- | src/renderer/tr_main.c | 192 | ||||
-rw-r--r-- | src/renderer/tr_model.c | 70 | ||||
-rw-r--r-- | src/renderer/tr_public.h | 1 | ||||
-rw-r--r-- | src/renderer/tr_scene.c | 2 | ||||
-rw-r--r-- | src/renderer/tr_shade.c | 45 | ||||
-rw-r--r-- | src/renderer/tr_shader.c | 85 | ||||
-rw-r--r-- | src/renderer/tr_shadows.c | 4 | ||||
-rw-r--r-- | src/renderer/tr_types.h | 43 |
14 files changed, 637 insertions, 212 deletions
diff --git a/src/renderer/tr_backend.c b/src/renderer/tr_backend.c index 9c9b841a..5eed467a 100644 --- a/src/renderer/tr_backend.c +++ b/src/renderer/tr_backend.c @@ -522,7 +522,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { int fogNum, oldFogNum; int entityNum, oldEntityNum; int dlighted, oldDlighted; - qboolean depthRange, oldDepthRange; + qboolean depthRange, oldDepthRange, isCrosshair, wasCrosshair; int i; drawSurf_t *drawSurf; int oldSort; @@ -540,6 +540,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { oldShader = NULL; oldFogNum = -1; oldDepthRange = qfalse; + wasCrosshair = qfalse; oldDlighted = qfalse; oldSort = -1; depthRange = qfalse; @@ -574,7 +575,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { // change the modelview matrix if needed // if ( entityNum != oldEntityNum ) { - depthRange = qfalse; + depthRange = isCrosshair = qfalse; if ( entityNum != ENTITYNUM_WORLD ) { backEnd.currentEntity = &backEnd.refdef.entities[entityNum]; @@ -591,9 +592,13 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { R_TransformDlights( backEnd.refdef.num_dlights, backEnd.refdef.dlights, &backEnd.or ); } - if ( backEnd.currentEntity->e.renderfx & RF_DEPTHHACK ) { + if(backEnd.currentEntity->e.renderfx & RF_DEPTHHACK) + { // hack the depth range to prevent view model from poking into walls depthRange = qtrue; + + if(backEnd.currentEntity->e.renderfx & RF_CROSSHAIR) + isCrosshair = qtrue; } } else { backEnd.currentEntity = &tr.worldEntity; @@ -608,15 +613,54 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) { qglLoadMatrixf( backEnd.or.modelMatrix ); // - // change depthrange if needed + // change depthrange. Also change projection matrix so first person weapon does not look like coming + // out of the screen. // - if ( oldDepthRange != depthRange ) { - if ( depthRange ) { - qglDepthRange (0, 0.3); - } else { + if (oldDepthRange != depthRange || wasCrosshair != isCrosshair) + { + if (depthRange) + { + if(backEnd.viewParms.stereoFrame != STEREO_CENTER) + { + if(isCrosshair) + { + if(oldDepthRange) + { + // was not a crosshair but now is, change back proj matrix + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(backEnd.viewParms.projectionMatrix); + qglMatrixMode(GL_MODELVIEW); + } + } + else + { + viewParms_t temp = backEnd.viewParms; + + R_SetupProjection(&temp, r_znear->value, qfalse); + + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(temp.projectionMatrix); + qglMatrixMode(GL_MODELVIEW); + } + } + + if(!oldDepthRange) + qglDepthRange (0, 0.3); + } + else + { + if(!wasCrosshair && backEnd.viewParms.stereoFrame != STEREO_CENTER) + { + qglMatrixMode(GL_PROJECTION); + qglLoadMatrixf(backEnd.viewParms.projectionMatrix); + qglMatrixMode(GL_MODELVIEW); + } + qglDepthRange (0, 1); } + oldDepthRange = depthRange; + wasCrosshair = isCrosshair; } oldEntityNum = entityNum; @@ -989,6 +1033,42 @@ void RB_ShowImages( void ) { } +/* +============= +RB_ColorMask + +============= +*/ +const void *RB_ColorMask(const void *data) +{ + const colorMaskCommand_t *cmd = data; + + qglColorMask(cmd->rgba[0], cmd->rgba[1], cmd->rgba[2], cmd->rgba[3]); + + return (const void *)(cmd + 1); +} + +/* +============= +RB_ClearDepth + +============= +*/ +const void *RB_ClearDepth(const void *data) +{ + const clearDepthCommand_t *cmd = data; + + if(tess.numIndexes) + RB_EndSurface(); + + // texture swapping test + if (r_showImages->integer) + RB_ShowImages(); + + qglClear(GL_DEPTH_BUFFER_BIT); + + return (const void *)(cmd + 1); +} /* ============= @@ -1085,7 +1165,12 @@ void RB_ExecuteRenderCommands( const void *data ) { case RC_VIDEOFRAME: data = RB_TakeVideoFrameCmd( data ); break; - + case RC_COLORMASK: + data = RB_ColorMask(data); + break; + case RC_CLEARDEPTH: + data = RB_ClearDepth(data); + break; case RC_END_OF_LIST: default: // stop rendering on this thread diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c index 2eff8349..1f63f9f0 100644 --- a/src/renderer/tr_bsp.c +++ b/src/renderer/tr_bsp.c @@ -1322,6 +1322,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 550ce4e8..1b39c56b 100644 --- a/src/renderer/tr_cmds.c +++ b/src/renderer/tr_cmds.c @@ -294,6 +294,38 @@ void RE_StretchPic ( float x, float y, float w, float h, cmd->t2 = t2; } +#define MODE_RED_CYAN 1 +#define MODE_RED_BLUE 2 +#define MODE_RED_GREEN 3 +#define MODE_MAX MODE_RED_GREEN + +void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode) +{ + rgba[0] = rgba[1] = rgba[2] = rgba[3] = GL_TRUE; + + if(colormode > MODE_MAX) + { + if(stereoFrame == STEREO_LEFT) + stereoFrame = STEREO_RIGHT; + else if(stereoFrame == STEREO_RIGHT) + stereoFrame = STEREO_LEFT; + + colormode -= MODE_MAX; + } + + if(stereoFrame == STEREO_LEFT) + rgba[1] = rgba[2] = GL_FALSE; + else if(stereoFrame == STEREO_RIGHT) + { + rgba[0] = GL_FALSE; + + if(colormode == MODE_RED_BLUE) + rgba[1] = GL_FALSE; + else if(colormode == MODE_RED_GREEN) + rgba[2] = GL_FALSE; + } +} + /* ==================== @@ -304,7 +336,8 @@ for each RE_EndFrame ==================== */ void RE_BeginFrame( stereoFrame_t stereoFrame ) { - drawBufferCommand_t *cmd; + drawBufferCommand_t *cmd = NULL; + colorMaskCommand_t *colcmd = NULL; if ( !tr.registered ) { return; @@ -371,26 +404,22 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { R_SetColorMappings(); } - // check for errors - if ( !r_ignoreGLErrors->integer ) { - int err; + // check for errors + if ( !r_ignoreGLErrors->integer ) + { + int err; R_SyncRenderThread(); - if ( ( err = qglGetError() ) != GL_NO_ERROR ) { - ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err ); - } - } - - // - // draw buffer stuff - // - cmd = R_GetCommandBuffer( sizeof( *cmd ) ); - if ( !cmd ) { - return; + if ((err = qglGetError()) != GL_NO_ERROR) + ri.Error(ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err); } - cmd->commandId = RC_DRAW_BUFFER; - if ( glConfig.stereoEnabled ) { + if (glConfig.stereoEnabled) { + if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) + return; + + cmd->commandId = RC_DRAW_BUFFER; + if ( stereoFrame == STEREO_LEFT ) { cmd->buffer = (int)GL_BACK_LEFT; } else if ( stereoFrame == STEREO_RIGHT ) { @@ -398,16 +427,78 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { } else { ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); } - } else { - if ( stereoFrame != STEREO_CENTER ) { - ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); + } + else + { + if(r_anaglyphMode->integer) + { + if(r_anaglyphMode->modified) + { + // clear both, front and backbuffer. + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + qglDrawBuffer(GL_FRONT); + qglClear(GL_COLOR_BUFFER_BIT); + qglDrawBuffer(GL_BACK); + qglClear(GL_COLOR_BUFFER_BIT); + + r_anaglyphMode->modified = qfalse; + } + + if(stereoFrame == STEREO_LEFT) + { + if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) + return; + + if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) + return; + } + else if(stereoFrame == STEREO_RIGHT) + { + clearDepthCommand_t *cldcmd; + + if( !(cldcmd = R_GetCommandBuffer(sizeof(*cldcmd))) ) + return; + + cldcmd->commandId = RC_CLEARDEPTH; + + if( !(colcmd = R_GetCommandBuffer(sizeof(*colcmd))) ) + return; + } + else + ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame ); + + R_SetColorMode(colcmd->rgba, stereoFrame, r_anaglyphMode->integer); + colcmd->commandId = RC_COLORMASK; } - if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) { - cmd->buffer = (int)GL_FRONT; - } else { - cmd->buffer = (int)GL_BACK; + else + { + if(stereoFrame != STEREO_CENTER) + ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame ); + + if( !(cmd = R_GetCommandBuffer(sizeof(*cmd))) ) + return; + } + + if(cmd) + { + cmd->commandId = RC_DRAW_BUFFER; + + if(r_anaglyphMode->modified) + { + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + r_anaglyphMode->modified = qfalse; + } + + if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) + cmd->buffer = (int)GL_FRONT; + else + cmd->buffer = (int)GL_BACK; } } + + tr.refdef.stereoFrame = stereoFrame; } diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c index 9a0b01fc..a2e92e49 100644 --- a/src/renderer/tr_image.c +++ b/src/renderer/tr_image.c @@ -183,6 +183,7 @@ void R_ImageList_f( void ) { ri.Printf( PRINT_ALL, "RGB8" ); break; case GL_RGB4_S3TC: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: ri.Printf( PRINT_ALL, "S3TC " ); break; case GL_RGBA4: @@ -559,7 +560,16 @@ static void Upload32( unsigned *data, c = width*height; scan = ((byte *)data); samples = 3; - if (!lightMap) { + + if(lightMap) + { + if(r_greyscale->integer) + internalFormat = GL_LUMINANCE; + else + internalFormat = GL_RGB; + } + else + { for ( i = 0; i < c; i++ ) { if ( scan[i*4+0] > rMax ) @@ -583,41 +593,68 @@ static void Upload32( unsigned *data, // select proper internal format if ( samples == 3 ) { - if ( glConfig.textureCompression == TC_S3TC ) + if(r_greyscale->integer) { - internalFormat = GL_RGB4_S3TC; - } - else if ( r_texturebits->integer == 16 ) - { - internalFormat = GL_RGB5; - } - else if ( r_texturebits->integer == 32 ) - { - internalFormat = GL_RGB8; + if(r_texturebits->integer == 16) + internalFormat = GL_LUMINANCE8; + else if(r_texturebits->integer == 32) + internalFormat = GL_LUMINANCE16; + else + internalFormat = GL_LUMINANCE; } else { - internalFormat = 3; + if ( glConfig.textureCompression == TC_S3TC_ARB ) + { + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + } + else if ( glConfig.textureCompression == TC_S3TC ) + { + internalFormat = GL_RGB4_S3TC; + } + else if ( r_texturebits->integer == 16 ) + { + internalFormat = GL_RGB5; + } + else if ( r_texturebits->integer == 32 ) + { + internalFormat = GL_RGB8; + } + else + { + internalFormat = GL_RGB; + } } } else if ( samples == 4 ) { - if ( r_texturebits->integer == 16 ) - { - internalFormat = GL_RGBA4; - } - else if ( r_texturebits->integer == 32 ) + if(r_greyscale->integer) { - internalFormat = GL_RGBA8; + if(r_texturebits->integer == 16) + internalFormat = GL_LUMINANCE8_ALPHA8; + else if(r_texturebits->integer == 32) + internalFormat = GL_LUMINANCE16_ALPHA16; + else + internalFormat = GL_LUMINANCE_ALPHA; } else { - internalFormat = 4; + if ( r_texturebits->integer == 16 ) + { + internalFormat = GL_RGBA4; + } + else if ( r_texturebits->integer == 32 ) + { + internalFormat = GL_RGBA8; + } + else + { + internalFormat = GL_RGBA; + } } } - } else { - internalFormat = 3; } + // copy or resample data as appropriate for first MIP level if ( ( scaled_width == width ) && ( scaled_height == height ) ) { diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c index 426579d7..685f6fa1 100644 --- a/src/renderer/tr_init.c +++ b/src/renderer/tr_init.c @@ -47,11 +47,18 @@ cvar_t *r_displayRefresh; cvar_t *r_detailTextures; cvar_t *r_znear; +cvar_t *r_zproj; +cvar_t *r_stereoSeparation; cvar_t *r_smp; cvar_t *r_showSmp; cvar_t *r_skipBackEnd; +cvar_t *r_stereoEnabled; +cvar_t *r_anaglyphMode; + +cvar_t *r_greyscale; + cvar_t *r_ignorehwgamma; cvar_t *r_measureOverdraw; @@ -90,7 +97,6 @@ cvar_t *r_logFile; cvar_t *r_stencilbits; cvar_t *r_depthbits; cvar_t *r_colorbits; -cvar_t *r_stereo; cvar_t *r_primitives; cvar_t *r_texturebits; @@ -149,30 +155,6 @@ int max_polys; cvar_t *r_maxpolyverts; int max_polyverts; -static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ) -{ - if ( shouldBeIntegral ) - { - if ( ( int ) cv->value != cv->integer ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value ); - ri.Cvar_Set( cv->name, va( "%d", cv->integer ) ); - } - } - - if ( cv->value < minVal ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal ); - ri.Cvar_Set( cv->name, va( "%f", minVal ) ); - } - else if ( cv->value > maxVal ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal ); - ri.Cvar_Set( cv->name, va( "%f", maxVal ) ); - } -} - - #define GENERIC_HW_R_PICMIP_DEFAULT "0" #define GENERIC_HW_R_TEXTUREMODE_DEFAULT "GL_LINEAR_MIPMAP_LINEAR" @@ -925,11 +907,10 @@ void R_Register( void ) r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH ); - AssertCvarRange( r_picmip, 0, 16, qtrue ); + ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue ); r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_texturebits = ri.Cvar_Get( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_colorbits = ri.Cvar_Get( "r_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_stereo = ri.Cvar_Get( "r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_stencilbits = ri.Cvar_Get( "r_stencilbits", "8", CVAR_ARCHIVE | CVAR_LATCH ); r_depthbits = ri.Cvar_Get( "r_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_overBrightBits = ri.Cvar_Get ("r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH ); @@ -943,13 +924,15 @@ void R_Register( void ) r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", 0); r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH); r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH); + r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH ); + r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH); // // temporary latched variables that can only change over a restart // r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH ); - AssertCvarRange( r_displayRefresh, 0, 200, qtrue ); + ri.Cvar_CheckRange( r_displayRefresh, 0, 200, qtrue ); r_fullbright = ri.Cvar_Get ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT ); r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH ); r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_LATCH ); @@ -962,7 +945,9 @@ void R_Register( void ) r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE ); r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE ); r_znear = ri.Cvar_Get( "r_znear", "1", CVAR_CHEAT ); - AssertCvarRange( r_znear, 0.001f, 200, qtrue ); + ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse ); + r_zproj = ri.Cvar_Get( "r_zproj", "64", CVAR_ARCHIVE ); + r_stereoSeparation = ri.Cvar_Get( "r_stereoSeparation", "64", CVAR_ARCHIVE ); r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE ); r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE ); r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE ); @@ -986,6 +971,8 @@ void R_Register( void ) r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT ); r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT ); + r_anaglyphMode = ri.Cvar_Get("r_anaglyphMode", "0", CVAR_ARCHIVE); + // // temporary variables that can change at any time // diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h index 76acb15e..b8d89af8 100644 --- a/src/renderer/tr_local.h +++ b/src/renderer/tr_local.h @@ -323,10 +323,12 @@ typedef struct { struct shaderCommands_s; -#define LIGHTMAP_2D -4 // shader is for 2D rendering -#define LIGHTMAP_BY_VERTEX -3 // pre-lit triangle models -#define LIGHTMAP_WHITEIMAGE -2 -#define LIGHTMAP_NONE -1 +// any change in the LIGHTMAP_* defines here MUST be reflected in +// R_FindShader() in tr_bsp.c +#define LIGHTMAP_2D -4 // shader is for 2D rendering +#define LIGHTMAP_BY_VERTEX -3 // pre-lit triangle models +#define LIGHTMAP_WHITEIMAGE -2 +#define LIGHTMAP_NONE -1 typedef enum { CT_FRONT_SIDED, @@ -434,6 +436,8 @@ typedef struct { vec3_t vieworg; vec3_t viewaxis[3]; // transformation matrix + stereoFrame_t stereoFrame; + int time; // time in milliseconds for shader effects and other time dependent rendering issues int rdflags; // RDF_NOWORLDMODEL, etc @@ -505,6 +509,7 @@ typedef struct { cplane_t frustum[4]; vec3_t visBounds[2]; float zFar; + stereoFrame_t stereoFrame; } viewParms_t; @@ -990,11 +995,12 @@ extern cvar_t *r_verbose; // used for verbose debug spew extern cvar_t *r_ignoreFastPath; // allows us to ignore our Tess fast paths extern cvar_t *r_znear; // near Z clip plane +extern cvar_t *r_zproj; // z distance of projection plane +extern cvar_t *r_stereoSeparation; // separation of cameras for stereo rendering extern cvar_t *r_stencilbits; // number of desired stencil bits extern cvar_t *r_depthbits; // number of desired depth bits extern cvar_t *r_colorbits; // number of desired color bits, only relevant for fullscreen -extern cvar_t *r_stereo; // desired pixelformat stereo flag extern cvar_t *r_texturebits; // number of desired texture bits // 0 = use framebuffer depth // 16 = use 16-bit textures @@ -1085,6 +1091,11 @@ extern cvar_t *r_smp; extern cvar_t *r_showSmp; extern cvar_t *r_skipBackEnd; +extern cvar_t *r_stereoEnabled; +extern cvar_t *r_anaglyphMode; + +extern cvar_t *r_greyscale; + extern cvar_t *r_ignoreGLErrors; extern cvar_t *r_overBrightBits; @@ -1133,6 +1144,7 @@ int R_CullLocalBox (vec3_t bounds[2]); int R_CullPointAndRadius( vec3_t origin, float radius ); int R_CullLocalPointAndRadius( vec3_t origin, float radius ); +void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum); void R_RotateForEntity( const trRefEntity_t *ent, const viewParms_t *viewParms, orientationr_t *or ); /* @@ -1611,6 +1623,18 @@ typedef struct { qboolean motionJpeg; } videoFrameCommand_t; +typedef struct +{ + int commandId; + + GLboolean rgba[4]; +} colorMaskCommand_t; + +typedef struct +{ + int commandId; +} clearDepthCommand_t; + typedef enum { RC_END_OF_LIST, RC_SET_COLOR, @@ -1619,7 +1643,9 @@ typedef enum { RC_DRAW_BUFFER, RC_SWAP_BUFFERS, RC_SCREENSHOT, - RC_VIDEOFRAME + RC_VIDEOFRAME, + RC_COLORMASK, + RC_CLEARDEPTH } renderCommand_t; diff --git a/src/renderer/tr_main.c b/src/renderer/tr_main.c index bbe94236..3d908316 100644 --- a/src/renderer/tr_main.c +++ b/src/renderer/tr_main.c @@ -382,7 +382,7 @@ void R_RotateForViewer (void) /* ** SetFarClip */ -static void SetFarClip( void ) +static void R_SetFarClip( void ) { float farthestCornerDistance = 0; int i; @@ -443,97 +443,144 @@ static void SetFarClip( void ) tr.viewParms.zFar = sqrt( farthestCornerDistance ); } +/* +================= +R_SetupFrustum + +Set up the culling frustum planes for the current view using the results we got from computing the first two rows of +the projection matrix. +================= +*/ +void R_SetupFrustum (viewParms_t *dest, float xmin, float xmax, float ymax, float zProj, float stereoSep) +{ + vec3_t ofsorigin; + float oppleg, adjleg, length; + int i; + + if(stereoSep == 0 && xmin != -xmax) + { + // symmetric case can be simplified + VectorCopy(dest->or.origin, ofsorigin); + + length = sqrt(xmax * xmax + zProj * zProj); + oppleg = xmax / length; + adjleg = zProj / length; + + VectorScale(dest->or.axis[0], oppleg, dest->frustum[0].normal); + VectorMA(dest->frustum[0].normal, adjleg, dest->or.axis[1], dest->frustum[0].normal); + + VectorScale(dest->or.axis[0], oppleg, dest->frustum[1].normal); + VectorMA(dest->frustum[1].normal, -adjleg, dest->or.axis[1], dest->frustum[1].normal); + } + else + { + // In stereo rendering, due to the modification of the projection matrix, dest->or.origin is not the + // actual origin that we're rendering so offset the tip of the view pyramid. + VectorMA(dest->or.origin, stereoSep, dest->or.axis[1], ofsorigin); + + oppleg = xmax + stereoSep; + length = sqrt(oppleg * oppleg + zProj * zProj); + VectorScale(dest->or.axis[0], oppleg / length, dest->frustum[0].normal); + VectorMA(dest->frustum[0].normal, zProj / length, dest->or.axis[1], dest->frustum[0].normal); + + oppleg = xmin + stereoSep; + length = sqrt(oppleg * oppleg + zProj * zProj); + VectorScale(dest->or.axis[0], -oppleg / length, dest->frustum[1].normal); + VectorMA(dest->frustum[1].normal, -zProj / length, dest->or.axis[1], dest->frustum[1].normal); + } + + length = sqrt(ymax * ymax + zProj * zProj); + oppleg = ymax / length; + adjleg = zProj / length; + + VectorScale(dest->or.axis[0], oppleg, dest->frustum[2].normal); + VectorMA(dest->frustum[2].normal, adjleg, dest->or.axis[2], dest->frustum[2].normal); + + VectorScale(dest->or.axis[0], oppleg, dest->frustum[3].normal); + VectorMA(dest->frustum[3].normal, -adjleg, dest->or.axis[2], dest->frustum[3].normal); + + for (i=0 ; i<4 ; i++) { + dest->frustum[i].type = PLANE_NON_AXIAL; + dest->frustum[i].dist = DotProduct (ofsorigin, dest->frustum[i].normal); + SetPlaneSignbits( &dest->frustum[i] ); + } +} /* =============== R_SetupProjection =============== */ -void R_SetupProjection( void ) { +void R_SetupProjection(viewParms_t *dest, float zProj, qboolean computeFrustum) +{ float xmin, xmax, ymin, ymax; - float width, height, depth; - float zNear, zFar; + float width, height, stereoSep = r_stereoSeparation->value; - // dynamically compute far clip plane distance - SetFarClip(); + /* + * offset the view origin of the viewer for stereo rendering + * by setting the projection matrix appropriately. + */ - // - // set up projection matrix - // - zNear = r_znear->value; - zFar = tr.viewParms.zFar; + if(stereoSep != 0) + { + if(dest->stereoFrame == STEREO_LEFT) + stereoSep = zProj / r_stereoSeparation->value; + else if(dest->stereoFrame == STEREO_RIGHT) + stereoSep = zProj / -r_stereoSeparation->value; + else + stereoSep = 0; + } - ymax = zNear * tan( tr.refdef.fov_y * M_PI / 360.0f ); + ymax = zProj * tan(dest->fovY * M_PI / 360.0f); ymin = -ymax; - xmax = zNear * tan( tr.refdef.fov_x * M_PI / 360.0f ); + xmax = zProj * tan(dest->fovX * M_PI / 360.0f); xmin = -xmax; width = xmax - xmin; height = ymax - ymin; - depth = zFar - zNear; - - tr.viewParms.projectionMatrix[0] = 2 * zNear / width; - tr.viewParms.projectionMatrix[4] = 0; - tr.viewParms.projectionMatrix[8] = ( xmax + xmin ) / width; // normally 0 - tr.viewParms.projectionMatrix[12] = 0; - - tr.viewParms.projectionMatrix[1] = 0; - tr.viewParms.projectionMatrix[5] = 2 * zNear / height; - tr.viewParms.projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0 - tr.viewParms.projectionMatrix[13] = 0; - - tr.viewParms.projectionMatrix[2] = 0; - tr.viewParms.projectionMatrix[6] = 0; - tr.viewParms.projectionMatrix[10] = -( zFar + zNear ) / depth; - tr.viewParms.projectionMatrix[14] = -2 * zFar * zNear / depth; - - tr.viewParms.projectionMatrix[3] = 0; - tr.viewParms.projectionMatrix[7] = 0; - tr.viewParms.projectionMatrix[11] = -1; - tr.viewParms.projectionMatrix[15] = 0; + + dest->projectionMatrix[0] = 2 * zProj / width; + dest->projectionMatrix[4] = 0; + dest->projectionMatrix[8] = (xmax + xmin + 2 * stereoSep) / width; + dest->projectionMatrix[12] = 2 * zProj * stereoSep / width; + + dest->projectionMatrix[1] = 0; + dest->projectionMatrix[5] = 2 * zProj / height; + dest->projectionMatrix[9] = ( ymax + ymin ) / height; // normally 0 + dest->projectionMatrix[13] = 0; + + dest->projectionMatrix[3] = 0; + dest->projectionMatrix[7] = 0; + dest->projectionMatrix[11] = -1; + dest->projectionMatrix[15] = 0; + + // Now that we have all the data for the projection matrix we can also setup the view frustum. + if(computeFrustum) + R_SetupFrustum(dest, xmin, xmax, ymax, zProj, stereoSep); } /* -================= -R_SetupFrustum +=============== +R_SetupProjectionZ -Setup that culling frustum planes for the current view -================= +Sets the z-component transformation part in the projection matrix +=============== */ -void R_SetupFrustum (void) { - int i; - float xs, xc; - float ang; - - ang = tr.viewParms.fovX / 180 * M_PI * 0.5f; - xs = sin( ang ); - xc = cos( ang ); - - VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[0].normal ); - VectorMA( tr.viewParms.frustum[0].normal, xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[0].normal ); - - VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[1].normal ); - VectorMA( tr.viewParms.frustum[1].normal, -xc, tr.viewParms.or.axis[1], tr.viewParms.frustum[1].normal ); - - ang = tr.viewParms.fovY / 180 * M_PI * 0.5f; - xs = sin( ang ); - xc = cos( ang ); - - VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[2].normal ); - VectorMA( tr.viewParms.frustum[2].normal, xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[2].normal ); - - VectorScale( tr.viewParms.or.axis[0], xs, tr.viewParms.frustum[3].normal ); - VectorMA( tr.viewParms.frustum[3].normal, -xc, tr.viewParms.or.axis[2], tr.viewParms.frustum[3].normal ); +void R_SetupProjectionZ(viewParms_t *dest) +{ + float zNear, zFar, depth; + + zNear = r_znear->value; + zFar = dest->zFar; + depth = zFar - zNear; - for (i=0 ; i<4 ; i++) { - tr.viewParms.frustum[i].type = PLANE_NON_AXIAL; - tr.viewParms.frustum[i].dist = DotProduct (tr.viewParms.or.origin, tr.viewParms.frustum[i].normal); - SetPlaneSignbits( &tr.viewParms.frustum[i] ); - } + dest->projectionMatrix[2] = 0; + dest->projectionMatrix[6] = 0; + dest->projectionMatrix[10] = -( zFar + zNear ) / depth; + dest->projectionMatrix[14] = -2 * zFar * zNear / depth; } - /* ================= R_MirrorPoint @@ -1252,7 +1299,12 @@ void R_GenerateDrawSurfs( void ) { // this needs to be done before entities are // added, because they use the projection // matrix for lod calculation - R_SetupProjection (); + + // dynamically compute far clip plane distance + R_SetFarClip(); + + // we know the size of the clipping volume. Now set the rest of the projection matrix. + R_SetupProjectionZ (&tr.viewParms); R_AddEntitySurfaces (); } @@ -1337,7 +1389,7 @@ void R_RenderView (viewParms_t *parms) { // set viewParms.world R_RotateForViewer (); - R_SetupFrustum (); + R_SetupProjection(&tr.viewParms, r_zproj->value, qtrue); R_GenerateDrawSurfs(); diff --git a/src/renderer/tr_model.c b/src/renderer/tr_model.c index 8fdd0adb..b4ca744f 100644 --- a/src/renderer/tr_model.c +++ b/src/renderer/tr_model.c @@ -405,13 +405,13 @@ static qboolean R_LoadMD3 (model_t *mod, int lod, void *buffer, const char *mod_ } +#ifdef RAVENMD4 /* ================= R_LoadMDR ================= */ -#ifdef RAVENMD4 static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char *mod_name ) { int i, j, k, l; @@ -445,10 +445,10 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char mod->type = MOD_MDR; - pinmodel->numFrames = LittleLong(pinmodel->numFrames); - pinmodel->numBones = LittleLong(pinmodel->numBones); - pinmodel->ofsFrames = LittleLong(pinmodel->ofsFrames); - + LL(pinmodel->numFrames); + LL(pinmodel->numBones); + LL(pinmodel->ofsFrames); + // This is a model that uses some type of compressed Bones. We don't want to uncompress every bone for each rendered frame // over and over again, we'll uncompress it in this function already, so we must adjust the size of the target md4. if(pinmodel->ofsFrames < 0) @@ -459,6 +459,14 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char size += pinmodel->numFrames * pinmodel->numBones * ((sizeof(mdrBone_t) - sizeof(mdrCompBone_t))); } + // simple bounds check + if(pinmodel->numBones < 0 || + sizeof(*mdr) + pinmodel->numFrames * (sizeof(*frame) + (pinmodel->numBones - 1) * sizeof(*frame->bones)) > size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } + mod->dataSize += size; mod->md4 = mdr = ri.Hunk_Alloc( size, h_low ); @@ -471,8 +479,8 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char mdr->numBones = pinmodel->numBones; mdr->numLODs = LittleLong(pinmodel->numLODs); mdr->numTags = LittleLong(pinmodel->numTags); - // We don't care about offset values, we'll generate them ourselves while loading. - + // We don't care about the other offset values, we'll generate them ourselves while loading. + mod->numLods = mdr->numLODs; if ( mdr->numFrames < 1 ) @@ -491,7 +499,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char // compressed model... cframe = (mdrCompFrame_t *)((byte *) pinmodel - pinmodel->ofsFrames); - + for(i = 0; i < mdr->numFrames; i++) { for(j = 0; j < 3; j++) @@ -566,6 +574,13 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char // swap all the LOD's for ( l = 0 ; l < mdr->numLODs ; l++) { + // simple bounds check + if((byte *) (lod + 1) > (byte *) mdr + size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } + lod->numSurfaces = LittleLong(curlod->numSurfaces); // swap all the surfaces @@ -573,7 +588,15 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char lod->ofsSurfaces = (int)((byte *) surf - (byte *) lod); cursurf = (mdrSurface_t *) ((byte *)curlod + LittleLong(curlod->ofsSurfaces)); - for ( i = 0 ; i < lod->numSurfaces ; i++) { + for ( i = 0 ; i < lod->numSurfaces ; i++) + { + // simple bounds check + if((byte *) (surf + 1) > (byte *) mdr + size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } + // first do some copying stuff surf->ident = SF_MDR; @@ -617,6 +640,15 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char for(j = 0; j < surf->numVerts; j++) { + LL(curv->numWeights); + + // simple bounds check + if(curv->numWeights < 0 || (byte *) (v + 1) + (curv->numWeights - 1) * sizeof(*weight) > (byte *) mdr + size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } + v->normal[0] = LittleFloat(curv->normal[0]); v->normal[1] = LittleFloat(curv->normal[1]); v->normal[2] = LittleFloat(curv->normal[2]); @@ -624,7 +656,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char v->texCoords[0] = LittleFloat(curv->texCoords[0]); v->texCoords[1] = LittleFloat(curv->texCoords[1]); - v->numWeights = LittleLong(curv->numWeights); + v->numWeights = curv->numWeights; weight = &v->weights[0]; curweight = &curv->weights[0]; @@ -651,6 +683,13 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char surf->ofsTriangles = (int)((byte *) tri - (byte *) surf); curtri = (mdrTriangle_t *)((byte *) cursurf + LittleLong(cursurf->ofsTriangles)); + // simple bounds check + if(surf->numTriangles < 0 || (byte *) (tri + surf->numTriangles) > (byte *) mdr + size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } + for(j = 0; j < surf->numTriangles; j++) { tri->indexes[0] = LittleLong(curtri->indexes[0]); @@ -681,6 +720,13 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char tag = (mdrTag_t *) lod; mdr->ofsTags = (int)((byte *) tag - (byte *) mdr); curtag = (mdrTag_t *) ((byte *)pinmodel + LittleLong(pinmodel->ofsTags)); + + // simple bounds check + if(mdr->numTags < 0 || (byte *) (tag + mdr->numTags) > (byte *) mdr + size) + { + ri.Printf(PRINT_WARNING, "R_LoadMDR: %s has broken structure.\n", mod_name); + return qfalse; + } for (i = 0 ; i < mdr->numTags ; i++) { @@ -691,7 +737,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char curtag++; } - // And finally we know the offset to the end. + // And finally we know the real offset to the end. mdr->ofsEnd = (int)((byte *) tag - (byte *) mdr); // phew! we're done. @@ -876,7 +922,7 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) { // NOTE: this sucks, for some reason the first stretch pic is never drawn // without this we'd see a white flash on a level load because the very // first time the level shot would not be drawn - RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0); +// RE_StretchPic(0, 0, 0, 0, 0, 0, 1, 1, 0); } //============================================================================= diff --git a/src/renderer/tr_public.h b/src/renderer/tr_public.h index e4e4d047..eac2cd29 100644 --- a/src/renderer/tr_public.h +++ b/src/renderer/tr_public.h @@ -132,6 +132,7 @@ typedef struct { cvar_t *(*Cvar_Get)( const char *name, const char *value, int flags ); void (*Cvar_Set)( const char *name, const char *value ); + void (*Cvar_CheckRange)( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ); void (*Cmd_AddCommand)( const char *name, void(*cmd)(void) ); void (*Cmd_RemoveCommand)( const char *name ); diff --git a/src/renderer/tr_scene.c b/src/renderer/tr_scene.c index a45d8f86..82084886 100644 --- a/src/renderer/tr_scene.c +++ b/src/renderer/tr_scene.c @@ -390,6 +390,8 @@ void RE_RenderScene( const refdef_t *fd ) { parms.fovX = tr.refdef.fov_x; parms.fovY = tr.refdef.fov_y; + + parms.stereoFrame = tr.refdef.stereoFrame; VectorCopy( fd->vieworg, parms.or.origin ); VectorCopy( fd->viewaxis[0], parms.or.axis[0] ); diff --git a/src/renderer/tr_shade.c b/src/renderer/tr_shade.c index 0214083b..dd8b81bb 100644 --- a/src/renderer/tr_shade.c +++ b/src/renderer/tr_shade.c @@ -456,9 +456,19 @@ static void ProjectDlightTexture_altivec( void ) { radius = dl->radius; scale = 1.0f / radius; - floatColor[0] = dl->color[0] * 255.0f; - floatColor[1] = dl->color[1] * 255.0f; - floatColor[2] = dl->color[2] * 255.0f; + if(r_greyscale->integer) + { + float luminance; + + luminance = (dl->color[0] * 255.0f + dl->color[1] * 255.0f + dl->color[2] * 255.0f) / 3; + floatColor[0] = floatColor[1] = floatColor[2] = luminance; + } + else + { + floatColor[0] = dl->color[0] * 255.0f; + floatColor[1] = dl->color[1] * 255.0f; + floatColor[2] = dl->color[2] * 255.0f; + } floatColorVec0 = vec_ld(0, floatColor); floatColorVec1 = vec_ld(11, floatColor); floatColorVec0 = vec_perm(floatColorVec0,floatColorVec0,floatColorVecPerm); @@ -600,9 +610,20 @@ static void ProjectDlightTexture_scalar( void ) { radius = dl->radius; scale = 1.0f / radius; - floatColor[0] = dl->color[0] * 255.0f; - floatColor[1] = dl->color[1] * 255.0f; - floatColor[2] = dl->color[2] * 255.0f; + if(r_greyscale->integer) + { + float luminance; + + luminance = (dl->color[0] * 255.0f + dl->color[1] * 255.0f + dl->color[2] * 255.0f) / 3; + floatColor[0] = floatColor[1] = floatColor[2] = luminance; + } + else + { + floatColor[0] = dl->color[0] * 255.0f; + floatColor[1] = dl->color[1] * 255.0f; + floatColor[2] = dl->color[2] * 255.0f; + } + for ( i = 0 ; i < tess.numVertexes ; i++, texCoords += 2, colors += 4 ) { int clip = 0; vec3_t dist; @@ -939,6 +960,18 @@ static void ComputeColors( shaderStage_t *pStage ) break; } } + + // if in greyscale rendering mode turn all color values into greyscale. + if(r_greyscale->integer) + { + int scale; + + for(i = 0; i < tess.numVertexes; i++) + { + scale = (tess.svars.colors[i][0] + tess.svars.colors[i][1] + tess.svars.colors[i][2]) / 3; + tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; + } + } } /* diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c index 499c335a..f3f8a331 100644 --- a/src/renderer/tr_shader.c +++ b/src/renderer/tr_shader.c @@ -1433,7 +1433,6 @@ static qboolean ParseShader( char **text ) // stage definition else if ( token[0] == '{' ) { - // 20051019 misantropia -- fix buffer overrun. if ( s >= MAX_SHADER_STAGES ) { ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name ); return qfalse; @@ -2153,7 +2152,7 @@ static shader_t *FinishShader( void ) { // // set appropriate stage information // - for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { + for ( stage = 0; stage < MAX_SHADER_STAGES; ) { shaderStage_t *pStage = &stages[stage]; if ( !pStage->active ) { @@ -2164,17 +2163,33 @@ static shader_t *FinishShader( void ) { if ( !pStage->bundle[0].image[0] ) { ri.Printf( PRINT_WARNING, "Shader %s has a stage with no image\n", shader.name ); pStage->active = qfalse; + stage++; continue; } // // ditch this stage if it's detail and detail textures are disabled // - if ( pStage->isDetail && !r_detailTextures->integer ) { - if ( stage < ( MAX_SHADER_STAGES - 1 ) ) { - memmove( pStage, pStage + 1, sizeof( *pStage ) * ( MAX_SHADER_STAGES - stage - 1 ) ); - Com_Memset( pStage + 1, 0, sizeof( *pStage ) ); + if ( pStage->isDetail && !r_detailTextures->integer ) + { + int index; + + for(index = stage + 1; index < MAX_SHADER_STAGES; index++) + { + if(!stages[index].active) + break; + } + + if(index < MAX_SHADER_STAGES) + memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage)); + else + { + if(stage + 1 < MAX_SHADER_STAGES) + memmove(pStage, pStage + 1, sizeof(*pStage) * (index - stage - 1)); + + Com_Memset(&stages[index - 1], 0, sizeof(*stages)); } + continue; } @@ -2243,6 +2258,8 @@ static shader_t *FinishShader( void ) { } } } + + stage++; } // there are times when you will need to manually apply a sort to @@ -2430,6 +2447,10 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag // lightmaps if ( lightmapIndex >= 0 && lightmapIndex >= tr.numLightmaps ) { 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_StripExtension(name, strippedName, sizeof(strippedName)); @@ -2564,7 +2585,7 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_ hash = generateHashValue(name, FILE_HASH_SIZE); - // 20051020 misantropia -- probably not necessary since this function + // 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 ) { @@ -2869,7 +2890,7 @@ static void ScanAndLoadShaderFiles( void ) char *oldp, *token, *hashMem; int shaderTextHashTableSizes[MAX_SHADERTEXT_HASH], hash, size; - long sum = 0; + long sum = 0, summand; // scan for shader files shaderFiles = ri.FS_ListFiles( "scripts", ".shader", &numShaderFiles ); @@ -2890,10 +2911,38 @@ static void ScanAndLoadShaderFiles( void ) Com_sprintf( filename, sizeof( filename ), "scripts/%s", shaderFiles[i] ); ri.Printf( PRINT_DEVELOPER, "...loading '%s'\n", filename ); - sum += ri.FS_ReadFile( filename, (void **)&buffers[i] ); - if ( !buffers[i] ) { + summand = ri.FS_ReadFile( filename, (void **)&buffers[i] ); + + if ( !buffers[i] ) ri.Error( ERR_DROP, "Couldn't load %s", filename ); + + // Do a simple check on the shader structure in that file to make sure one bad shader file cannot fuck up all other shaders. + p = buffers[i]; + while(1) + { + token = COM_ParseExt(&p, qtrue); + + if(!*token) + break; + + oldp = p; + + token = COM_ParseExt(&p, qtrue); + if(token[0] != '{' && token[1] != '\0') + { + ri.Printf(PRINT_WARNING, "WARNING: Bad shader file %s has incorrect syntax.\n", filename); + ri.FS_FreeFile(buffers[i]); + buffers[i] = NULL; + break; + } + + SkipBracedSection(&oldp); + p = oldp; } + + + if (buffers[i]) + sum += summand; } // build single large buffer @@ -2901,12 +2950,16 @@ static void ScanAndLoadShaderFiles( void ) s_shaderText[ 0 ] = '\0'; // free in reverse order, so the temp files are all dumped - for ( i = numShaderFiles - 1; i >= 0 ; i-- ) { - p = &s_shaderText[strlen(s_shaderText)]; - strcat( s_shaderText, buffers[i] ); - ri.FS_FreeFile( buffers[i] ); - COM_Compress(p); - strcat( s_shaderText, "\n" ); + for ( i = numShaderFiles - 1; i >= 0 ; i-- ) + { + if(buffers[i]) + { + p = &s_shaderText[strlen(s_shaderText)]; + strcat( s_shaderText, buffers[i] ); + ri.FS_FreeFile( buffers[i] ); + COM_Compress(p); + strcat( s_shaderText, "\n" ); + } } // free up memory diff --git a/src/renderer/tr_shadows.c b/src/renderer/tr_shadows.c index 19d40466..a9f34130 100644 --- a/src/renderer/tr_shadows.c +++ b/src/renderer/tr_shadows.c @@ -156,6 +156,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 ) { @@ -216,6 +217,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 ); @@ -246,7 +248,7 @@ void RB_ShadowTessEnd( void ) { // 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_types.h b/src/renderer/tr_types.h index a1c338b1..82270b91 100644 --- a/src/renderer/tr_types.h +++ b/src/renderer/tr_types.h @@ -25,27 +25,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define __TR_TYPES_H -#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces -#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing +#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces +#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing // renderfx flags -#define RF_MINLIGHT 1 // allways have some light (viewmodel, some items) -#define RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites) -#define RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob) -#define RF_DEPTHHACK 8 // for view weapon Z crunching -#define RF_NOSHADOW 64 // don't add stencil shadows - -#define RF_LIGHTING_ORIGIN 128 // use refEntity->lightingOrigin instead of refEntity->origin - // for lighting. This allows entities to sink into the floor - // with their origin going solid, and allows all parts of a - // player to get the same lighting -#define RF_SHADOW_PLANE 256 // use refEntity->shadowPlane -#define RF_WRAP_FRAMES 512 // mod the model frames by the maxframes to allow continuous - // animation without needing to know the frame count +#define RF_MINLIGHT 0x0001 // allways have some light (viewmodel, some items) +#define RF_THIRD_PERSON 0x0002 // don't draw through eyes, only mirrors (player bodies, chat sprites) +#define RF_FIRST_PERSON 0x0004 // only draw through eyes (view weapon, damage blood blob) +#define RF_DEPTHHACK 0x0008 // for view weapon Z crunching + +#define RF_CROSSHAIR 0x0010 // This item is a cross hair and will draw over everything similar to + // DEPTHHACK in stereo rendering mode, with the difference that the + // projection matrix won't be hacked to reduce the stereo separation as + // is done for the gun. + +#define RF_NOSHADOW 0x0040 // don't add stencil shadows + +#define RF_LIGHTING_ORIGIN 0x0080 // use refEntity->lightingOrigin instead of refEntity->origin + // for lighting. This allows entities to sink into the floor + // with their origin going solid, and allows all parts of a + // player to get the same lighting + +#define RF_SHADOW_PLANE 0x0100 // use refEntity->shadowPlane +#define RF_WRAP_FRAMES 0x0200 // mod the model frames by the maxframes to allow continuous // refdef flags -#define RDF_NOWORLDMODEL 1 // used for player configuration screen -#define RDF_HYPERSPACE 4 // teleportation effect +#define RDF_NOWORLDMODEL 0x0001 // used for player configuration screen +#define RDF_HYPERSPACE 0x0004 // teleportation effect typedef struct { vec3_t xyz; @@ -146,7 +152,8 @@ typedef enum { */ typedef enum { TC_NONE, - TC_S3TC + TC_S3TC, // this is for the GL_S3_s3tc extension. + TC_S3TC_ARB // this is for the GL_EXT_texture_compression_s3tc extension. } textureCompression_t; typedef enum { |