From 513c538fba431a614f609a4ec8bf09c068a5bbc9 Mon Sep 17 00:00:00 2001 From: leilei- Date: Tue, 20 May 2025 06:30:51 -0400 Subject: [PATCH] A bunch of things - s_interrupt - allows sounds to be interrupted by the same sound or entity channel - new dynamic light calculation for vertex lighting, affecting vertex color (no projected dlight textures) - rgbGen material for allowing calculation for diffuse, specular, emmissive vertex colors by hex values - rgbMod shader command allowing new vertex color effects - removed deprecated R_ParseStageSimple, it never worked as intended - r_slowness gone. Use llvmpipe, PCem, or a slow computer instead. - Spring cleaning of old deprecated/broken post-process GLSL experiments - r_anime broke in 2015 - r_tvMode - well, shaderglass exists now - r_motionblur - Bad technique, too much memory - t_pslettize - slow, relies on shader's lookup of a vector table - r_film - bad on well-lit maps - r_retroAA - this broke early too. also looked bad. would rather implement FSAA 4x - cl_consoleScale : makes the console more 640x480 sized on any higher res. Also affects notify messages, so you can read chat easier - cl_consoleColor also affects the line at the bottom. Also new default colors - If consoleShader can't load (which will happen with some mods), it will fallback to a flat-colored console. - Generic'd the red/blue team names. We will not be having missionpack clans. - SDL2: Clicking the red X now does something: you can leave!!! If it sucks.... hit da bricks!! real winners quit - s_xmp_startPattern - makes the tracker song play a different pattern (for use with sub-songs) - fixed xmp playback as xmp explicitly requires a length of the module now. Fixes issue #96 - suppress the warning about non-22khz music, as mods are playing at the mixer's rate always, and this warning regards a much earlier (1999) unstable sound mixer. - deprecating r_modelshader because the shader got stale, old, buggy, and amd hates it now - r_shadeMethod will be something else (and not shader-based) - r_lightmapColorNorm : Make normalization of bright luxels an option, default is 1 (q3 behavior). - r_lightmapColorNorm 0 = no normalization, straight clamp, like Nightdive's vision of Quake2 - r_lightmapColorNorm 2 = experiment: normalize, but add some luminance on while maintaining the hue by normalizing again. This tries to restore more range on fully saturated colors - dropped SHADER_MAX_VERTEXES back to 1000 because raising it causes various unexpected issues, so dialing it down for now - raise MAX_IMAGE_ANIMATIONS to 16 because I've got a cool water shader using it and 8 is too choppy - Crash fix for older (<=2001) mods by trimming the string shared with ui module, so no overflow for them - jettisoning old proposed mme particle system that was never ever hooked up properly. - other small warning cleanup - r_shadeMethod : 0/1 = q3 behavior, 2 = ue1-ish behavior, 3 = mix of 1 and 2, -1 = one uniform color, 150-666 = a lod range to change between the 3 - r_monolightmaps : refactor - goes to the light data instead of the calculations and images - removed r_greyscale because this is a data-modifying novelty that would complicate support for loading compressed texture formats. This is better off as a post-process shader - environment mapping refactor, rewrite and cleanup - removed a lot of deprecated rgbGens - removed r_texdump (it never worked) - remove a few leftover broken postprocess things - Internal GLSL brightness shader, so gamma control can work without the glsl/brightness_fp.glsl file when r_ext_vertex_shader is 1 and r_alternateBrightness is 2. - r_skyTess - an attempt to make the complexity of skydomes an option so it could use less polygons. Has no effect on skyboxes --- code/client/cl_console.c | 70 +- code/client/cl_keys.c | 2 +- code/client/cl_main.c | 19 +- code/client/cl_scrn.c | 115 +- code/client/client.h | 5 +- code/client/fx_local.h | 476 ------ code/client/fx_main.c | 1569 -------------------- code/client/fx_parse.c | 2390 ------------------------------ code/client/fx_public.h | 35 - code/client/fx_types.h | 51 - code/client/snd_codec_xmp.c | 43 +- code/client/snd_dma.c | 32 +- code/client/snd_local.h | 4 + code/client/snd_main.c | 6 +- code/qcommon/q_shared.h | 2 +- code/qcommon/qfiles.h | 2 +- code/renderer_oa/tr_backend.c | 204 --- code/renderer_oa/tr_bloom.c | 990 +------------ code/renderer_oa/tr_bsp.c | 72 +- code/renderer_oa/tr_extensions.c | 6 + code/renderer_oa/tr_image.c | 260 +--- code/renderer_oa/tr_init.c | 169 +-- code/renderer_oa/tr_local.h | 143 +- code/renderer_oa/tr_mesh.c | 2 +- code/renderer_oa/tr_scene.c | 16 +- code/renderer_oa/tr_shade.c | 294 +--- code/renderer_oa/tr_shade_calc.c | 1139 +++++++------- code/renderer_oa/tr_shader.c | 1369 +++++------------ code/renderer_oa/tr_sky.c | 145 +- code/sdl/sdl_glimp.c | 73 - code/sdl/sdl_input.c | 1 + code/server/sv_init.c | 3 +- 32 files changed, 1617 insertions(+), 8090 deletions(-) delete mode 100644 code/client/fx_local.h delete mode 100644 code/client/fx_main.c delete mode 100644 code/client/fx_parse.c delete mode 100644 code/client/fx_public.h delete mode 100644 code/client/fx_types.h diff --git a/code/client/cl_console.c b/code/client/cl_console.c index 9ea4b19e..e1e4ac60 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -517,6 +517,8 @@ DRAWING ============================================================================== */ +extern cvar_t *cl_consoleScale; // leilei - scale the console + /* ================ @@ -536,7 +538,7 @@ void Con_DrawInput (void) { re.SetColor( con.color ); - SCR_DrawSmallChar( con.xadjust + 1 * SMALLCHAR_WIDTH, y, ']' ); + SCR_DrawSmallChar( con.xadjust + 1 * SMALLCHAR_WIDTH, y, ']' ,2); Field_Draw( &g_consoleField, con.xadjust + 2 * SMALLCHAR_WIDTH, y, SCREEN_WIDTH - 3 * SMALLCHAR_WIDTH, qtrue, qtrue ); @@ -587,7 +589,7 @@ void Con_DrawNotify (void) currentColor = (text[x]>>8) % NUMBER_OF_COLORS; re.SetColor( g_color_table[currentColor] ); } - SCR_DrawSmallChar( cl_conXOffset->integer + con.xadjust + (x+1)*SMALLCHAR_WIDTH, v, text[x] & 0xff ); + SCR_DrawSmallChar( cl_conXOffset->integer + con.xadjust + (x+1)*SMALLCHAR_WIDTH, v, text[x] & 0xff ,2); } v += SMALLCHAR_HEIGHT; @@ -636,6 +638,17 @@ void Con_DrawSolidConsole( float frac ) { int currentColor; vec4_t color; + if (cl_consoleScale->integer && (cls.glconfig.vidWidth > SCREEN_WIDTH)) + { + lines = SCREEN_HEIGHT * frac; + if (lines <= 0) + return; + + if (lines > SCREEN_HEIGHT ) + lines = SCREEN_HEIGHT; + } + else + { lines = cls.glconfig.vidHeight * frac; if (lines <= 0) return; @@ -646,6 +659,7 @@ void Con_DrawSolidConsole( float frac ) { // on wide screens, we will center the text con.xadjust = 0; SCR_AdjustFrom640( &con.xadjust, NULL, NULL, NULL ); + } // draw the background y = frac * SCREEN_HEIGHT; @@ -667,9 +681,31 @@ void Con_DrawSolidConsole( float frac ) { } } - color[0] = 1; - color[1] = 0; - color[2] = 0; + // leilei - normalize our custom color for the line + //color[0] = 1; + //color[1] = 0; // was 1 pre-1.25 + //color[2] = 0; + + // leilei - normalize from our custom console color and apply it to the line + { + float max; + float rgb[3]; + + rgb[0] = cl_consoleColor[0]->value; + rgb[1] = cl_consoleColor[1]->value; + rgb[2] = cl_consoleColor[2]->value; + + max = rgb[0] + rgb[1] + rgb[2] / 3; + + if (max > 0) + { + color[0] = rgb[0] / max; + color[1] = rgb[1] / max; + color[2] = rgb[2] / max; + } + } + + if( !cl_consoleType->integer ) color[3] = 1; SCR_FillRect( 0, y, SCREEN_WIDTH, 2, color ); @@ -677,14 +713,24 @@ void Con_DrawSolidConsole( float frac ) { // draw the version number - re.SetColor( g_color_table[ColorIndex(COLOR_RED)] ); + re.SetColor( g_color_table[ColorIndex(cl_consoleAccent->integer)] ); i = strlen( Q3_VERSION ); - for (x=0 ; xinteger && (cls.glconfig.vidWidth > SCREEN_WIDTH)){ + for (x=0 ; xinteger)] ); for (x=0 ; x>8) % NUMBER_OF_COLORS; re.SetColor( g_color_table[currentColor] ); } - SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, text[x] & 0xff ); + SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, text[x] & 0xff, 2 ); } } diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index 1bd9cf9a..c37f3c64 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -378,7 +378,7 @@ void Field_VariableSizeDraw( field_t *edit, int x, int y, int width, int size, q i = drawLen - strlen( str ); if ( size == SMALLCHAR_WIDTH ) { - SCR_DrawSmallChar( x + ( edit->cursor - prestep - i ) * size, y, cursorChar ); + SCR_DrawSmallChar( x + ( edit->cursor - prestep - i ) * size, y, cursorChar, 2 ); } else { str[0] = cursorChar; str[1] = 0; diff --git a/code/client/cl_main.c b/code/client/cl_main.c index c9c07853..96b0909c 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -124,6 +124,8 @@ cvar_t *cl_consoleType; cvar_t *cl_consoleColor[4]; cvar_t *cl_consoleHeight; +cvar_t *cl_consoleAccent; // leilei - change version and line color +cvar_t *cl_consoleScale; // leilei - scale the console clientActive_t cl; clientConnection_t clc; @@ -3115,6 +3117,11 @@ void CL_InitRenderer( void ) { cls.charSetShader = re.RegisterShader( "gfx/2d/bigchars" ); cls.whiteShader = re.RegisterShader( "white" ); cls.consoleShader = re.RegisterShader( "console" ); + if (!cls.consoleShader) // leilei - fallback console type if it fails + { + Cvar_Set("cl_consoleType", "2"); + Com_Printf( "Console shader failed to load, falling back to simple console\n"); + } g_console_field_width = cls.glconfig.vidWidth / SMALLCHAR_WIDTH - 2; g_consoleField.widthInChars = g_console_field_width; } @@ -3552,12 +3559,14 @@ void CL_Init( void ) { cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE); cl_consoleType = Cvar_Get( "cl_consoleType", "0", CVAR_ARCHIVE ); - cl_consoleColor[0] = Cvar_Get( "cl_consoleColorRed", "1", CVAR_ARCHIVE ); - cl_consoleColor[1] = Cvar_Get( "cl_consoleColorGreen", "0", CVAR_ARCHIVE ); - cl_consoleColor[2] = Cvar_Get( "cl_consoleColorBlue", "0", CVAR_ARCHIVE ); + cl_consoleColor[0] = Cvar_Get( "cl_consoleColorRed", "0.104", CVAR_ARCHIVE ); + cl_consoleColor[1] = Cvar_Get( "cl_consoleColorGreen", "0.187", CVAR_ARCHIVE ); + cl_consoleColor[2] = Cvar_Get( "cl_consoleColorBlue", "0.312", CVAR_ARCHIVE ); cl_consoleColor[3] = Cvar_Get( "cl_consoleColorAlpha", "0.8", CVAR_ARCHIVE ); cl_consoleHeight = Cvar_Get("cl_consoleHeight", "0.5", CVAR_ARCHIVE); + cl_consoleAccent = Cvar_Get("cl_consoleAccent", "61" , CVAR_ARCHIVE); // leilei - change version and scroll color + cl_consoleScale = Cvar_Get ("cl_consoleScale" , "1" , CVAR_ARCHIVE); // leilei - console/notify text scale // userinfo Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -3567,8 +3576,8 @@ void CL_Init( void ) { Cvar_Get ("headmodel", "sarge", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("team_model", "james", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("team_headmodel", "*james", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("g_redTeam", "Stroggs", CVAR_SERVERINFO | CVAR_ARCHIVE); - Cvar_Get ("g_blueTeam", "Pagans", CVAR_SERVERINFO | CVAR_ARCHIVE); + Cvar_Get ("g_redTeam", "Red", CVAR_SERVERINFO | CVAR_ARCHIVE); + Cvar_Get ("g_blueTeam", "Blue", CVAR_SERVERINFO | CVAR_ARCHIVE); Cvar_Get ("color1", "4", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("color2", "5", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("handicap", "100", CVAR_USERINFO | CVAR_ARCHIVE ); diff --git a/code/client/cl_scrn.c b/code/client/cl_scrn.c index 831d5ef7..f81e2236 100644 --- a/code/client/cl_scrn.c +++ b/code/client/cl_scrn.c @@ -84,6 +84,35 @@ void SCR_AdjustFrom640( float *x, float *y, float *w, float *h ) { } } + +/* +================ +SCR_AdjustFrom480 + +leilei - Adjusted for resolution and screen aspect ratio.... but from vertical only so the aspect is ok +================ +*/ +void SCR_AdjustFrom480( float *x, float *y, float *w, float *h ) { + float yscale; + + // scale for screen sizes + yscale = cls.glconfig.vidHeight / 480.0; + + if ( x ) { + *x *= yscale; + } + if ( y ) { + *y *= yscale; + } + if ( w ) { + *w *= yscale; + } + if ( h ) { + *h *= yscale; + } +} + + /* ================ SCR_FillRect @@ -157,32 +186,78 @@ static void SCR_DrawChar( int x, int y, float size, int ch ) { ** SCR_DrawSmallChar ** small chars are drawn at native screen resolution */ -void SCR_DrawSmallChar( int x, int y, int ch ) { +void SCR_DrawSmallChar( int x, int y, int ch, int scalemode ) { int row, col; float frow, fcol; float size; - ch &= 255; + if ((scalemode) && (cl_consoleScale->integer) && (cls.glconfig.vidWidth > SCREEN_WIDTH)) + { + // leilei - ideally, I want to have the same amount of lines as 640x480 on any higher resolution to keep it readable, + // while horizontally it's also like 640x480 but keeping up a gap to the right so the characters are still 1:2 aspect. + // like idTech 4. + // in 640x480 on a normal pulled down console, there are 12 lines, 6.5 lines on a half pull, and 29 for a full console + int row, col; + float frow, fcol; + float ax, ay, aw, ah; + float size; + ch &= 255; + + if ( ch == ' ' ) { + return; + } + + if ( y < -SMALLCHAR_HEIGHT ) { + return; + } + + ax = x; + ay = y; + aw = SMALLCHAR_WIDTH ; + ah = SMALLCHAR_HEIGHT; + if (scalemode == 2) + SCR_AdjustFrom480( &ax, &ay, &aw, &ah ); + else + SCR_AdjustFrom640( &ax, &ay, &aw, &ah ); - if ( ch == ' ' ) { - return; + row = ch>>4; + col = ch&15; + + frow = row*0.0625; + fcol = col*0.0625; + size = 0.0625; + + re.DrawStretchPic( ax, ay, aw, ah, + fcol, frow, + fcol + size, frow + size, + cls.charSetShader ); + + } - - if ( y < -SMALLCHAR_HEIGHT ) { - return; + else + { + ch &= 255; + + if ( ch == ' ' ) { + return; + } + + if ( y < -SMALLCHAR_HEIGHT ) { + return; + } + + row = ch>>4; + col = ch&15; + + frow = row*0.0625; + fcol = col*0.0625; + size = 0.0625; + + re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, + fcol, frow, + fcol + size, frow + size, + cls.charSetShader ); } - - row = ch>>4; - col = ch&15; - - frow = row*0.0625; - fcol = col*0.0625; - size = 0.0625; - - re.DrawStretchPic( x, y, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, - fcol, frow, - fcol + size, frow + size, - cls.charSetShader ); } @@ -286,7 +361,7 @@ void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, continue; } } - SCR_DrawSmallChar( xx, y, *s ); + SCR_DrawSmallChar( xx, y, *s, 2 ); xx += SMALLCHAR_WIDTH; s++; } diff --git a/code/client/client.h b/code/client/client.h index a3a939bc..47e073af 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -433,6 +433,9 @@ extern cvar_t *cl_consoleKeys; extern cvar_t *cl_consoleType; extern cvar_t *cl_consoleColor[4]; +extern cvar_t *cl_consoleScale; +extern cvar_t *cl_consoleAccent; + extern cvar_t *cl_consoleHeight; #ifdef USE_MUMBLE @@ -582,7 +585,7 @@ void SCR_DrawNamedPic( float x, float y, float width, float height, const char * void SCR_DrawBigString( int x, int y, const char *s, float alpha, qboolean noColorEscape ); // draws a string with embedded color control characters with fade void SCR_DrawBigStringColor( int x, int y, const char *s, vec4_t color, qboolean noColorEscape ); // ignores embedded color control characters void SCR_DrawSmallStringExt( int x, int y, const char *string, float *setColor, qboolean forceColor, qboolean noColorEscape ); -void SCR_DrawSmallChar( int x, int y, int ch ); +void SCR_DrawSmallChar( int x, int y, int ch, int scalemode ); // diff --git a/code/client/fx_local.h b/code/client/fx_local.h deleted file mode 100644 index 04e9351c..00000000 --- a/code/client/fx_local.h +++ /dev/null @@ -1,476 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Sjoerd van der Berg ( harekiet @ gmail.com ) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// fx_local.h -- private fx definitions - -#define FX_HASH_SHIFT 8 -#define FX_HASH_SIZE ( 1 << FX_HASH_SHIFT ) -#define FX_HASH_MASK (FX_HASH_SIZE - 1) - -#define FX_ACTIVE_HASH_SHIFT 5 -#define FX_ACTIVE_HASH_SIZE ( 1 << FX_ACTIVE_HASH_SHIFT ) -#define FX_ACTIVE_HASH_MASK (FX_ACTIVE_HASH_SIZE - 1) - -#define FX_MAX_SCRIPTS 4096 - -#define FX_MAX_ENTITIES (16*1024) - -#define FX_EMIT_TRACE 0x001 -#define FX_EMIT_SINK 0x002 -#define FX_EMIT_MOVE 0x004 -#define FX_EMIT_PARENT 0x010 -#define FX_EMIT_IMPACT 0x020 - -#define FX_EMIT_MASKSIZE 16 //Probably enough space - -#define FX_ENT_STATIONARY 0x001 -#define FX_ENT_DEAD 0x002 - -#define FX_SCRIPT_PARENT 0x001 -#define FX_STACK_SIZE 128 -#define FX_VECTOR_PARENT 0x10000 - -#define FX_MASK_PARENT 0x00001 -#define FX_MASK_ORIGIN 0x00002 -#define FX_MASK_VELOCITY 0x00004 -#define FX_MASK_SHADER 0x00008 -#define FX_MASK_SIZE 0x00010 -#define FX_MASK_ROTATE 0x00020 -#define FX_MASK_COLOR 0x00040 - -#define FX_MASK_DIR 0x00080 -#define FX_MASK_MODEL 0x00100 -#define FX_MASK_AXIS 0x00200 -#define FX_MASK_ANGLES 0x00400 -#define FX_MASK_WIDTH 0x00800 -#define FX_MASK_T0 0x01000 -#define FX_MASK_T1 0x02000 -#define FX_MASK_T2 0x04000 -#define FX_MASK_T3 0x08000 -#define FX_MASK_V0 0x10000 -#define FX_MASK_V1 0x20000 -#define FX_MASK_V2 0x40000 -#define FX_MASK_V3 0x80000 - - - -struct fxHashEntry_s; -struct fxEntity_s; -struct fxInitScript_s; - -typedef struct fxAtive_s { - struct fxAtive_s *next; - unsigned int key1, key2; - int beenUsed; -} fxActive_t; - -//Making any changes to this order you'll also need to modify the mask/unpacking stuff -typedef struct { - vec3_t origin; - vec3_t velocity; - - float size, rotate; - color4ub_t color; - qhandle_t shader; - - vec3_t dir; - float width; - vec3_t angles; - qhandle_t model; - vec3_t axis[3]; - - float t0, t1, t2, t3; - vec3_t v0, v1, v2, v3; - const fxParent_t *parent; - - float lerp; - float loop; - float life; - - struct fxEntity_s *entity; - int shaderTime; - unsigned int key; - - int stackUsed; - float stackData[FX_STACK_SIZE]; -} fxRun_t; - -const void *fxRunMath( fxRun_t *run, const void *data, float *value ); -typedef const void *(*fxHandler_t)( fxRun_t *run, const void * ); - -static ID_INLINE const float *fxFloatSrc( const fxRun_t *run, int offset ) { - if ( offset & FX_VECTOR_PARENT) - return (float *) (((char *)run->parent) + (offset & ~FX_VECTOR_PARENT) ); - else - return (float *) (((char *)run) + offset ); -} - -static ID_INLINE float *fxFloatDst( const fxRun_t *run, int offset ) { - return (float *) (((char *)run) + offset ); -} - -typedef enum { - fxCmdHalt, - fxCmdSkip, - - fxCmdEmitter, - fxCmdKill, - fxCmdRepeat, - fxCmdOnce, - fxCmdIf, - fxCmdInterval, - fxCmdDistance, - - - fxCmdSprite, - fxCmdBeam, - fxCmdLight, - fxCmdDirModel, - fxCmdAnglesModel, - fxCmdAxisModel, - fxCmdQuad, - fxCmdRings, - fxCmdSpark, - fxCmdDecal, - - fxCmdTrace, - fxCmdScript, - - fxCmdColor, - fxCmdColorList, - fxCmdColorBlend, - fxCmdColorHue, - fxCmdColorScale, - fxCmdColorMath, - fxCmdColorFade, - fxCmdAlphaFade, - - fxCmdShader, - fxCmdShaderList, - fxCmdModel, - fxCmdModelList, - fxCmdSound, - fxCmdSoundList, - fxCmdLoopSound, - fxCmdVibrate, - - fxCmdPush, - fxCmdPop, - fxCmdPushParent, - - fxCmdScale, - fxCmdCopy, - fxCmdAdd, - fxCmdAddScale, - fxCmdSub, - fxCmdSubScale, - fxCmdRotateAround, - fxCmdInverse, - fxCmdNormalize, - fxCmdPerpendicular, - fxCmdRandom, - fxCmdClear, - fxCmdWobble, - fxCmdMakeAngles, - fxCmdValue, -} fxCommand_t; - -typedef struct { - int blockSize; - void *blockData; -} fxRunBlock_t; - -typedef struct fxScript_s { - fxHandle_t handle; - struct fxHashEntry_s *entry; - struct fxScript_s *remap; - unsigned int readMask; - void *data[0]; -} fxScript_t; - -typedef struct { - int renderfx; -} fxRunRender_t; - -typedef struct { - color4ub_t value; -} fxRunColor_t; -typedef struct { - unsigned int count; -} fxRunColorBlend_t; -typedef struct { - unsigned int count; -} fxRunColorList_t; -typedef struct { - float delay, scale; -} fxRunColorFade_t; -typedef struct { - unsigned int index; -} fxRunColorMath_t; -typedef struct { - color4ub_t value; -} fxRunAlpha_t; -typedef struct { - int size; -} fxRunAlphaScale_t; -typedef struct { - float delay, scale; -} fxRunAlphaFade_t; -typedef struct { - int size; -} fxRunRed_t; -typedef struct { - int size; -} fxRunGreen_t; -typedef struct { - int size; -} fxRunBlue_t; - -typedef struct { - unsigned short flags; - unsigned short size; - unsigned short emitRun; - unsigned short impactRun; - unsigned short deathRun; - unsigned short allocSize; - byte mask[FX_EMIT_MASKSIZE]; - float impactSpeed; - float bounceFactor; - float sinkDelay, sinkDepth; - float gravity; -} fxRunEmitter_t; - -typedef struct { - int src; - int dst; -} fxRunScale_t; -typedef struct { - int src; - int dst; -} fxRunWobble_t; -typedef struct { - int src; - int dst; -} fxRunCopy_t; -typedef struct { - int src; - int dst; -} fxRunMakeAngles_t; -typedef struct { - int dst; -} fxRunClear_t; -typedef struct { - int src; - int dst; -} fxRunInverse_t; -typedef struct { - int src; - int dst; -} fxRunNormalize_t; -typedef struct { - int src1; - int src2; - int dst; -} fxRunAdd_t; -typedef struct { - int src1; - int src2; - int dst; -} fxRunSub_t; -typedef struct { - int src; - int scale; - int dst; -} fxRunAddScale_t; -typedef struct { - int src; - int scale; - int dst; -} fxRunSubScale_t; -typedef struct { - int src; - int dir; - int dst; -} fxRunRotateAround_t; -typedef struct { - int src; - int dst; -} fxRunPerpendicular_t; -typedef struct { - int dst; -} fxRunRandom_t; - -typedef struct { - int dst; -} fxRunValue_t; - -typedef struct { - qhandle_t shader; -} fxRunShader_t; -typedef struct { - unsigned int count; -} fxRunShaderList_t; - -typedef struct { - qhandle_t model; -} fxRunModel_t; - -typedef struct { - unsigned int count; - qhandle_t list[0]; -} fxRunModelList_t; - -typedef struct { - int flags; - int life; -} fxRunDecal_t; - -typedef struct { - void *data; -} fxRunScript_t; - -typedef struct { - int count; - int offset; -} fxRunPush_t; - -typedef struct { - int count; - int offset; -} fxRunPushParent_t; - -typedef struct { - int count; - int offset; -} fxRunPop_t; - -typedef struct { - int size; -} fxRunRepeat_t; - -typedef struct { - int size; -} fxRunOnce_t; -typedef struct { - int beenUsed; -} fxActiveOnce_t; - - -typedef struct { - int size; -} fxRunInterval_t; -typedef struct { - int beenUsed; - int nextTime; -} fxActiveInterval_t; - -typedef struct { - int size; -} fxRunSkip_t; -typedef struct { - int testCount; - int elseStep; - int size; -} fxRunIf_t; -typedef struct { - int size; -} fxRunDistance_t; -typedef struct { - int beenUsed; - vec3_t lastOrigin; - float distance; -} fxActiveDistance_t; - -typedef struct { - float strength; -} fxRunVibrate_t; - -typedef struct { - unsigned int count; - sfxHandle_t handle[0]; -} fxRunSoundList_t; - -typedef struct { - sfxHandle_t handle; -} fxRunSound_t; - -typedef struct { - sfxHandle_t handle; -} fxRunLoopSound_t; - -typedef struct fxEntity_s { - struct fxEntity_s *next; - const fxRunEmitter_t *emitter; - - int flags; - int startTime; - float traceTime; - float moveTime, lifeScale; - - vec3_t origin, velocity; -} fxEntity_t; - -/* Just gonna stick with using next for now */ -typedef struct fxHashEntry_s { - const char *name; - const char *text; - fxScript_t *script; - struct fxHashEntry_s *next; -} fxHashEntry_t; - -#define FX_VIBRATE_QUEUE 32 -typedef struct { - fxScript_t *scripts[FX_MAX_SCRIPTS]; - fxHashEntry_t *entryHash[FX_HASH_SIZE]; - fxActive_t *activeHash[FX_ACTIVE_HASH_SIZE]; - - int scriptCount; - int *allocSearch; - int *allocStart; - int allocSize; - int time, oldTime; - float timeFraction; - float deltaTime; - int seed; - fxEntity_t *entityActive; - fxEntity_t *entityNew; - struct { - int entitySize, activeSize; - int entityCount, activeCount; - } last; - struct { - int used, time; - float offset, magnitude; - struct { - vec3_t origin; - float strength; - } queue[FX_VIBRATE_QUEUE]; - } vibrate; - struct { - fxHashEntry_t *entries; - } alloc; -} fxMain_t; - -void fxInitParser( void ); -void fxFreeMemory( void ); - -extern cvar_t *fx_Debug; -extern cvar_t *fx_Override; diff --git a/code/client/fx_main.c b/code/client/fx_main.c deleted file mode 100644 index 593d39c5..00000000 --- a/code/client/fx_main.c +++ /dev/null @@ -1,1569 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Sjoerd van der Berg ( harekiet @ gmail.com ) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// fx_main.c Run FX Scripts and provide several commands for them - -#include "client.h" -#include "fx_local.h" - -fxMain_t fx; -cvar_t *fx_Megs; -cvar_t *fx_Vibrate; -cvar_t *fx_Override; -cvar_t *fx_Debug; - -static ID_INLINE void fxMaskInput( const byte *mask, const void *readV, void *writeV ) { - const long *read = (long *)readV; - long *write = (long*)writeV; - - read += mask[0]; - mask++; - while (1) { - int count; - /* Copy blocks */ - if (!mask[0]) - break; - count = mask[0]; - do { - *write++ = *read++; - count--; - } while (count > 0); - /* Skip blocks */ - if (!mask[1]) - break; - read += mask[1]; - mask += 2; - } -} - - -static ID_INLINE void fxMaskOutput( const byte *mask, const void *readV, void *writeV ) { - const long *read = (long *)readV; - long *write = (long*)writeV; - - write += mask[0]; - mask++; - while (1) { - int count; - /* Copy blocks */ - if (!mask[0]) - break; - count = mask[0]; - do { - *write++ = *read++; - count--; - } while (count > 0); - /* Skip blocks */ - if (!mask[1]) - break; - write += mask[1]; - mask += 2; - } -} - - -//Some forward defines -static void *fxGetActive( unsigned int key1, unsigned int key2, int size ); -static const void *fxRun( fxRun_t *run, const void *data ); - -static ID_INLINE int fxRand( void ) { - fx.seed = (69069 * fx.seed + 1); - return fx.seed; -} -static ID_INLINE float fxRandom( void ) { - return (fxRand() & 0xffff) * (1.0f / 0x10000); -} - -/* Very simple allocation function */ -static void *fxAlloc( int size ) { - int *search = fx.allocSearch; - int *searchStart = search; - - size += sizeof( int ); - //TODO make size a multiple of sizeof (void *) - while (1) { - //Used block - if ( search[0] == size ) { - search[0] = -size; - fx.allocSearch = (int*)(((char *)search) + size); - return search + 1; - } else if ( search[0] > size ) { - fx.allocSearch = (int*)(((char *)search) + size); - fx.allocSearch[0] = search[0] - size; - search[0] = -size; - return search + 1; - } else if ( search[0] < 0 ) { - search = (int*)(((char *)search) - search[0]); - //Last block - } else if (!search[0] ) { - search = fx.allocStart; - //Free block but too small, find a free one after it and join - } else { - int *searchNext = (int*)(((char *)search) + search[0]); - /* Is the next one free, if so add it */ - if ( searchNext[0] > 0 ) { - search[0] += searchNext[0]; - /* Added the start one and still not enough room? */ - if ( searchStart == searchNext && search[0] < size ) - break; - continue; - } else { - search = searchNext; - } - } - /* Check if it went a full loop, out of space then */ - if ( search == searchStart) { - break; - } - } - if ( fx_Debug->integer ) { - Com_Printf("FX_Debug:Ran out of allocation space, needed %d\n", size ); - } else { - Com_Error( ERR_DROP, "FX Ran out of allocation space for %d bytes, increase fx_Megs\n", size ); - } - return 0; -} - -static void fxVibrate( const vec3_t position, float strength ) { - if ( fx.vibrate.used < FX_VIBRATE_QUEUE ) { - int i = fx.vibrate.used++; - VectorCopy( position, fx.vibrate.queue[i].origin ); - fx.vibrate.queue[i].strength = strength; - } -} - -static void fxDoVibrate( const vec3_t origin, const vec3_t position, float strength ) { - vec3_t dist; - float magnitude, oldmagnitude; - - VectorSubtract( origin, position, dist ); - - magnitude = 1.0f - VectorLength( dist ) / 1000.0; - if( magnitude <= 0 ) - return; - magnitude = strength * magnitude * magnitude; - - if( fx.vibrate.time ) { - // Adjust for current vibration - int time = fx.time - fx.vibrate.time; - if( time < 20 ) - time = 20; - oldmagnitude = fx.vibrate.magnitude / (time / 20.0f); - } - else { - oldmagnitude = 0; - } - - fx.vibrate.magnitude = magnitude + oldmagnitude; - if( fx.vibrate.magnitude < 0 ) - fx.vibrate.magnitude= 0; - - fx.vibrate.offset = fxRandom() * 360; // Always on the 'up' half - fx.vibrate.time = fx.time; -} - - -void FX_VibrateView( float scale, vec3_t origin, vec3_t angles ) { - int i, time; - float magnitude; - - scale *= fx_Vibrate->value; - if (scale <= 0) { - fx.vibrate.used = 0; - return; - } - for ( i = 0; i < fx.vibrate.used; i++ ) { - fxDoVibrate( origin, fx.vibrate.queue[i].origin, fx.vibrate.queue[i].strength * scale ); - } - fx.vibrate.used = 0; - if( !fx.vibrate.time ) - return; - - time = fx.time - fx.vibrate.time; - if( time < 20 ) - time = 20; - magnitude = ((fx.vibrate.magnitude > 100) ? 100 : fx.vibrate.magnitude) / (time / 20.0f); - if( magnitude <= 3 ) - { - // There's not enough vibration to care about - fx.vibrate.time = 0; - return; - } - - origin[2] += magnitude * 0.3 * sin( 1.4 * (fx.vibrate.offset + SQRTFAST(time)) ); - angles[ROLL] += magnitude * (0.1 * sin( 0.1 * (fx.vibrate.offset + SQRTFAST(time)) ) - 0.05); -} -static int fxSize( void *block ) { - return ((int*)block)[-1]; -} - -static void fxFree( void *block ) { - int *alloc = ((int*)block) - 1; - alloc[0] = -alloc[0]; -} - -static const void *fxRunDecal( const fxRun_t *run, const fxRunDecal_t *decal ) { - int i; - vec4_t color; - - for (i = 0;i<4;i++) - color[i] = run->color[i] * ( 1.0f / 255); - - re.DecalProject( run->shader, run->origin, run->dir, color, run->rotate, run->size, decal->flags, decal->life ); - return decal + 1; -} -static const void* fxRunBeam( const fxRun_t *run, const fxRunRender_t* render ) { - refBeam_t beam; - - VectorCopy( run->origin, beam.start ); - VectorAdd( beam.start, run->dir, beam.end ); - beam.width = run->size; - beam.rotateAngle = run->rotate; - beam.shaderTime = run->shaderTime; - beam.shader = run->shader; - beam.renderfx = render->renderfx; - Byte4Copy( run->color, beam.color ); - re.AddBeamToScene( &beam ); - return render + 1; -} - -static const void* fxRunSpark( const fxRun_t *run, const fxRunRender_t* render ) { - refBeam_t spark; - - VectorNormalize2( run->velocity, spark.end ); - VectorMA( run->origin, -0.5*run->size, spark.end, spark.start ); - VectorMA( run->origin, 0.5*run->size, spark.end, spark.end ); - spark.width = run->width; - spark.rotateAngle = 0; - spark.shaderTime = run->shaderTime; - spark.shader = run->shader; - spark.renderfx = render->renderfx; - Byte4Copy( run->color, spark.color ); - re.AddBeamToScene( &spark ); - return render + 1; -} - -static const void* fxRunRings( const fxRun_t *run, const fxRunRender_t* render ) { - refRings_t rings; - - VectorCopy( run->origin, rings.start ); - VectorAdd( rings.start, run->dir, rings.end ); - rings.radius = run->size; - rings.stepSize = run->width; - rings.shaderTime = run->shaderTime; - rings.shader = run->shader; - rings.renderfx = render->renderfx; - Byte4Copy( run->color, rings.color ); - re.AddRingsToScene( &rings ); - return render + 1; -} -static const void* fxRunSprite( const fxRun_t* run, const fxRunRender_t* render ) { - refSprite_t sprite; - VectorCopy( run->origin, sprite.origin ); - sprite.shader = run->shader; - sprite.radius = run->size; - sprite.rotation = run->rotate; - sprite.shaderTime = run->shaderTime; - Byte4Copy( run->color, sprite.color ); - sprite.renderfx = render->renderfx; - re.AddSpriteToScene( &sprite ); - return render + 1; -} - -static const void* fxRunQuad( const fxRun_t *run, const fxRunRender_t* render ) { - polyVert_t verts[4]; - vec3_t left, up; - - PerpendicularVector( up, run->dir ); - RotatePointAroundVector( left, run->dir, up, run->angles[ROLL] ); - CrossProduct( run->dir, left, up ); - - VectorScale( up, run->size, up ); - VectorScale( left, -run->size, left ); - verts[0].xyz[0] = run->origin[0] + left[0] + up[0]; - verts[0].xyz[1] = run->origin[1] + left[1] + up[1]; - verts[0].xyz[2] = run->origin[2] + left[2] + up[2]; - verts[1].xyz[0] = run->origin[0] - left[0] + up[0]; - verts[1].xyz[1] = run->origin[1] - left[1] + up[1]; - verts[1].xyz[2] = run->origin[2] - left[2] + up[2]; - verts[2].xyz[0] = run->origin[0] - left[0] - up[0]; - verts[2].xyz[1] = run->origin[1] - left[1] - up[1]; - verts[2].xyz[2] = run->origin[2] - left[2] - up[2]; - verts[3].xyz[0] = run->origin[0] + left[0] - up[0]; - verts[3].xyz[1] = run->origin[1] + left[1] - up[1]; - verts[3].xyz[2] = run->origin[2] + left[2] - up[2]; - - Byte4Copy( run->color, verts[0].modulate ); - Byte4Copy( run->color, verts[1].modulate ); - Byte4Copy( run->color, verts[2].modulate ); - Byte4Copy( run->color, verts[3].modulate ); - verts[0].st[0] = 0; verts[0].st[1] = 0; - verts[1].st[0] = 1; verts[1].st[1] = 0; - verts[2].st[0] = 1; verts[2].st[1] = 1; - verts[3].st[0] = 0; verts[3].st[1] = 1; - re.AddPolyToScene( run->shader, 4, verts, 1 ); - return render + 1; -} -static const void* fxRunAnglesModel( const fxRun_t *run, const fxRunRender_t* render ) { - refModel_t model; - - memset( &model, 0, sizeof( model )); - VectorCopy( run->origin, model.origin ); - VectorCopy( run->origin, model.oldorigin ); - - model.hModel = run->model; - model.customShader = run->shader; - model.shaderTime = run->shaderTime; - model.renderfx = render->renderfx; - Byte4Copy( run->color, model.shaderRGBA ); - - // Setup the axis from the angles - AnglesToAxis( run->angles, model.axis ); - if ( run->size > 0 && run->size != 1 ) { - VectorScale( model.axis[0], run->size, model.axis[0] ); - VectorScale( model.axis[1], run->size, model.axis[1] ); - VectorScale( model.axis[2], run->size, model.axis[2] ); - model.nonNormalizedAxes = qtrue; - } - re.AddModelToScene( &model ); - return render + 1; -} -static const void* fxRunDirModel( const fxRun_t *run, const fxRunRender_t* render ) { - refModel_t model; - - memset( &model, 0, sizeof( model )); - VectorCopy( run->origin, model.origin ); - VectorCopy( run->origin, model.oldorigin ); - - model.hModel = run->model; - model.customShader = run->shader; - model.shaderTime = run->shaderTime; - model.renderfx = render->renderfx; - Byte4Copy( run->color, model.shaderRGBA ); - - // Setup the axis from the angles - VectorCopy( run->dir, model.axis[0] ); - RotateAroundDirection( model.axis, run->rotate ); - if ( run->size != 1 ) { - VectorScale( model.axis[0], run->size, model.axis[0] ); - VectorScale( model.axis[1], run->size, model.axis[1] ); - VectorScale( model.axis[2], run->size, model.axis[2] ); - model.nonNormalizedAxes = qtrue; - } - re.AddModelToScene( &model ); - return render + 1; -} -static const void* fxRunAxisModel( const fxRun_t *run, const fxRunRender_t* render ) { - refModel_t model; - - memset( &model, 0, sizeof( model )); - VectorCopy( run->origin, model.origin ); - VectorCopy( run->origin, model.oldorigin ); - - model.hModel = run->model; - model.customShader = run->shader; - model.shaderTime = run->shaderTime; - model.renderfx = render->renderfx; - Byte4Copy( run->color, model.shaderRGBA ); - - // Setup the axis from the angles - if ( run->size != 1 ) { - VectorScale( run->axis[0], run->size, model.axis[0] ); - VectorScale( run->axis[1], run->size, model.axis[1] ); - VectorScale( run->axis[2], run->size, model.axis[2] ); - model.nonNormalizedAxes = qtrue; - } else { - VectorCopy( run->axis[0], model.axis[0] ); - VectorCopy( run->axis[1], model.axis[1] ); - VectorCopy( run->axis[2], model.axis[2] ); - model.nonNormalizedAxes = qfalse; - } - re.AddModelToScene( &model ); - return render + 1; -} -static void fxRunLight( fxRun_t *run ) { - float r = run->color[0] * ( 1 / 255.0f ); - float g = run->color[1] * ( 1 / 255.0f ); - float b = run->color[2] * ( 1 / 255.0f ); - re.AddLightToScene( run->origin, run->size, r, g, b); -} - -static void fxRunTrace( fxRun_t *run ) { - trace_t tr; - vec3_t end; - - VectorMA( run->origin, 8000, run->dir, end ); - CM_BoxTrace( &tr, run->origin, end, 0, 0, 0, CONTENTS_SOLID, qfalse ); - if ( tr.fraction < 1 ) { - VectorCopy( tr.endpos, run->origin ); - VectorCopy( tr.plane.normal, run->dir ); - } -} - -static const void *fxRunShader( fxRun_t *run, const fxRunShader_t *shader ) { - run->shader = shader->shader; - return shader + 1; -} -static const void *fxRunShaderList( fxRun_t *run, const fxRunShaderList_t *shaderList ) { - float i; - qhandle_t *list = (qhandle_t*)fxRunMath( run, shaderList + 1, &i ); - run->shader = list[ (unsigned int)(i * shaderList->count) % shaderList->count ]; - return list + shaderList->count; -} -static const void *fxRunModel( fxRun_t *run, const fxRunModel_t *model ) { - run->model = model->model; - return model + 1; -} -static const void *fxRunModelList( fxRun_t *run, const fxRunModelList_t *modelList ) { - float i; - qhandle_t *list = (qhandle_t*)fxRunMath( run, modelList + 1, &i ); - run->model = list[ (unsigned int)(i * modelList->count) % modelList->count ]; - return list + modelList->count; -} -static const void *fxRunSoundList( const fxRun_t *run, const fxRunSoundList_t *sound ) { - unsigned int index = fxRand() % sound->count; - S_StartSound( run->origin, 0, 0, sound->handle[index] ); - return &sound->handle[ sound->count ]; -} -static const void *fxRunSound( const fxRun_t *run, const fxRunSound_t *sound ) { - S_StartSound( run->origin, 0, 0, sound->handle ); - return sound + 1; -} -static const void *fxRunLoopSound( const fxRun_t *run, const fxRunLoopSound_t *loopSound ) { - S_LoopingSound( (void *)run->key, run->origin, run->velocity, loopSound->handle, 127 ); - return loopSound + 1; -} -static const void *fxRunColor( fxRun_t *run, const fxRunColor_t *color ) { - run->color[0] = color->value[0]; - run->color[1] = color->value[1]; - run->color[2] = color->value[2]; - return color + 1; -} -static const void *fxRunColorList( fxRun_t *run, const fxRunColorList_t *colorList ) { - float i; - color4ub_t *list = (color4ub_t*)fxRunMath( run, colorList + 1, &i ); - byte *newColor; - - newColor = list[(unsigned int)(i * colorList->count) % colorList->count ]; - - run->color[0] = newColor[0]; - run->color[1] = newColor[1]; - run->color[2] = newColor[2]; - return list + colorList->count; -} - -static const void *fxRunColorBlend( fxRun_t *run, const fxRunColorBlend_t *colorBlend ) { - float i; - unsigned int index; - int blend; - color4ub_t *list = (color4ub_t*)fxRunMath( run, colorBlend + 1, &i ); - const byte *start, *end; - - i *= colorBlend->count-1; - index = (int)( i ); - start = list[ index % colorBlend->count ]; - end = list[ (index + 1) % colorBlend->count ]; - blend = Q_ftol(i * 256.0f) & 255; - - run->color[0] = start[0] + ((( end[0] - start[0] ) * blend) >> 8); - run->color[1] = start[1] + ((( end[1] - start[1] ) * blend) >> 8); - run->color[2] = start[2] + ((( end[2] - start[2] ) * blend) >> 8); - return list + colorBlend->count; -} - -static const void *fxRunColorHue( fxRun_t *run, const void *data ) { - float i; - const void *next = fxRunMath( run, data, &i ); - float deg, angle, v; - - deg = (i * 360); - angle = DEG2RAD( fmodf( deg, 120)); - v = ((cos(angle) / cos((M_PI / 3) - angle)) + 1) / 3; - if ( deg <= 120) { - run->color[0] = (v*255); - run->color[1] = ((1-v)*255); - run->color[2] = 0; - } else if ( deg <= 240) { - run->color[0] = 0; - run->color[1] = (v*255); - run->color[2] = ((1-v)*255); - } else { - run->color[0] = ((1-v)*255); - run->color[1] = 0; - run->color[2] = (v*255); - } - return next; -} - -static const void *fxRunColorMath( fxRun_t *run, const fxRunColorMath_t *colorMath ) { - float i; - const void *next = fxRunMath( run, colorMath + 1, &i ); - byte *color = run->color + colorMath->index; - if ( i < 0) - color[0] = 0; - else if ( i > 1.0f) - color[0] = 255; - else - color[0] = Q_ftol( 255 * i ); - return next; -} - -static const void *fxRunColorScale( fxRun_t *run, const void *data ) { - float i; - const void *next = fxRunMath( run, data, &i ); - int s = Q_ftol(255 * i); - run->color[0] = (s * run->color[0]) >> 8; - run->color[1] = (s * run->color[1]) >> 8; - run->color[2] = (s * run->color[2]) >> 8; - return next; -} - -static const void *fxRunColorFade( fxRun_t *run, const fxRunColorFade_t *colorFade ) { - if ( run->lerp > colorFade->delay ) { - int s = 255 - (run->lerp - colorFade->delay) * 255 * (1.0f / (1.0f - colorFade->delay)); - run->color[0] = (s * run->color[0]) >> 8; - run->color[1] = (s * run->color[1]) >> 8; - run->color[2] = (s * run->color[2]) >> 8; - } - return colorFade + 1; -} - -static const void *fxRunAlphaFade( fxRun_t *run, const fxRunAlphaFade_t *alphaFade ) { - if ( run->lerp > alphaFade->delay ) { - unsigned int s = 255 + Q_ftol( (run->lerp - alphaFade->delay) * alphaFade->scale); - run->color[3] = (s * run->color[3]) >> 8; - } - return alphaFade + 1; -} - -static const void *fxRunVibrate( fxRun_t *run, const fxRunVibrate_t *vibrate) { - fxVibrate( run->origin, vibrate->strength ); - return vibrate + 1; -} - -static const void *fxRunScale( fxRun_t *run, const fxRunScale_t *scale) { - const float *src = fxFloatSrc( run, scale->src ); - float *dst = fxFloatDst( run, scale->dst ); - float v; - const void *next; - - next = fxRunMath( run, scale+1, &v ); - VectorScale( src, v, dst ); - return next; -} - -static const void *fxRunValue( fxRun_t *run, const fxRunValue_t *value) { - float *dst = fxFloatDst( run, value->dst ); - return fxRunMath( run, value + 1, dst ); -} - -static const void *fxRunClear( fxRun_t *run, const fxRunClear_t *clear) { - float *dst = fxFloatDst( run, clear->dst ); - VectorClear( dst ); - return clear + 1; -} - -static const void *fxRunAddScale( fxRun_t *run, const fxRunAddScale_t *addScale) { - const float *src = fxFloatSrc( run, addScale->src ); - const float *scale = fxFloatSrc( run, addScale->scale ); - float *dst = fxFloatDst( run, addScale->dst ); - float v; - const void *next; - - next = fxRunMath( run, addScale+1, &v ); - VectorMA( src, v, scale, dst ); - return next; -} - -static const void *fxRunSubScale( fxRun_t *run, const fxRunSubScale_t *subScale) { - const float *src = fxFloatSrc( run, subScale->src ); - const float *scale = fxFloatSrc( run, subScale->scale ); - float *dst = fxFloatDst( run, subScale->dst ); - float v; - const void *next; - - next = fxRunMath( run, subScale+1, &v ); - VectorMA( src, -v, scale, dst ); - return next; -} - - -static const void *fxRunAdd( fxRun_t *run, const fxRunAdd_t *add) { - const float *src1 = fxFloatSrc( run, add->src1 ); - const float *src2 = fxFloatSrc( run, add->src2 ); - float *dst = fxFloatDst( run, add->dst ); - VectorAdd( src1, src2, dst ); - return add + 1; -} - -static const void *fxRunSub( fxRun_t *run, const fxRunSub_t *sub) { - const float *src1 = fxFloatSrc( run, sub->src1 ); - const float *src2 = fxFloatSrc( run, sub->src2 ); - float *dst = fxFloatDst( run, sub->dst ); - VectorSubtract( src1, src2, dst ); - return sub + 1; -} - -static const void *fxRunRotateAround( fxRun_t *run, const fxRunRotateAround_t *rotateAround) { - const float *src = fxFloatSrc( run, rotateAround->src ); - const float *dir = fxFloatSrc( run, rotateAround->dir ); - float *dst = fxFloatDst( run, rotateAround->dst ); - float v; - const void *next; - - next = fxRunMath( run, rotateAround+1, &v ); - RotatePointAroundVector( dst, dir, src, v ); - return next; -} - -static const void *fxRunCopy( fxRun_t *run, const fxRunCopy_t *copy) { - const float *src = fxFloatSrc( run, copy->src ); - float *dst = fxFloatDst( run, copy->dst ); - - VectorCopy( src, dst ); - return copy + 1; -} - -static const void *fxRunInverse( fxRun_t *run, const fxRunInverse_t *inverse ) { - const float *src = fxFloatSrc( run, inverse->src ); - float *dst = fxFloatDst( run, inverse->dst ); - - dst[0] = -src[0]; - dst[1] = -src[1]; - dst[2] = -src[2]; - return inverse+1; -} - -static const void *fxRunNormalize( fxRun_t *run, const fxRunNormalize_t *normalize ) { - const float *src = fxFloatSrc( run, normalize->src ); - float *dst = fxFloatDst( run, normalize->dst ); - - VectorNormalize2( src, dst ); - return normalize+1; -} - -static const void *fxRunPerpendicular( fxRun_t *run, const fxRunPerpendicular_t *perpendicular ) { - const float *src = fxFloatSrc( run, perpendicular->src ); - float *dst = fxFloatDst( run, perpendicular->dst ); - - PerpendicularVector( dst, src ); - return perpendicular+1; -} - -static const void *fxRunWobble( fxRun_t *run, const fxRunWobble_t *wobble ) { - const float *src = fxFloatSrc( run, wobble->src ); - float *dst = fxFloatDst( run, wobble->dst ); - float v; - const void *next; - float angle, s; - vec3_t axis[3]; - - next = fxRunMath( run, wobble+1, &v ); - - /* Check for the unlikely upward/downward vector */ - - VectorCopy( src, axis[0] ); - RotateAroundDirection( axis, fxRandom() * 360 ); - angle = DEG2RAD( v ); - s = cos( angle ); - VectorScale( axis[0], s, dst ); - s = sin( angle ); - VectorMA( dst, s, axis[2], dst ); - return next; -} - -static const void *fxRunMakeAngles( fxRun_t *run, const fxRunMakeAngles_t *makeAngles ) { - const float *src = fxFloatSrc( run, makeAngles->src ); - float *dst = fxFloatDst( run, makeAngles->dst ); - - vectoangles( src, dst ); - return makeAngles + 1; -} - -static const void *fxRunRandom( fxRun_t *run, const fxRunRandom_t *random ) { - float *dst = fxFloatDst( run, random->dst ); - - float yaw = fxRandom() * 2 * M_PI; - float pitch = fxRandom() * 2 * M_PI; - float cp = cos ( pitch ); - float sp = sin ( pitch ); - float cy = cos ( yaw ); - float sy = sin ( yaw ); - - dst[0] = cp*cy; - dst[1] = cp*sy; - dst[2] = -sp; - return random + 1; -} - -static const void *fxRunEmitter( fxRun_t *run, const fxRunEmitter_t *emitter ) { - fxEntity_t *entity; - - entity = fxAlloc( emitter->allocSize ); - if ( entity ) { - float life; - - entity->next = fx.entityNew; - fx.entityNew = entity; - - entity->startTime = fx.time; - fxRunMath( run, emitter + 1, &life ); - entity->lifeScale = 1.0f / (life * 1000); - entity->traceTime = 0; - entity->moveTime = 0; - entity->flags = 0; - VectorCopy( run->origin, entity->origin ); - VectorCopy( run->velocity, entity->velocity ); - entity->emitter = emitter; - fxMaskInput( emitter->mask, run->velocity + 3, entity + 1 ); - } - return ((byte *)emitter) + emitter->size; -} - -const void *fxRunRepeat( fxRun_t *run, const fxRunRepeat_t *repeat ) { - int i, count; - const void *next; - float v, loopScale; - - next = fxRunMath( run, repeat + 1, &v ); - count = Q_ftol(v); - loopScale = 1.0 / count; - for (i = 0; i < count; i++ ) { - run->loop = i * loopScale; - fxRun( run, next ); - } - return ((char *)repeat) + repeat->size; - } - -const void *fxRunIf( fxRun_t *run, const fxRunIf_t *runIf ) { - int i; - const void *next; - float v; - - next = runIf + 1; - for ( i = 0; itestCount;i++) { - int *blockSize; - next = fxRunMath( run, next, &v ); - blockSize = (int *)next; - next = blockSize + 1; - if ( v ) { - fxRun( run, next ); - return ((char *)runIf) + runIf->size; - } else { - /* Skip the block for this if case */ - next = ((char *)(next)) + blockSize[0]; - } - } - if ( runIf->elseStep) { - return next; - } else { - return ((char *)runIf) + runIf->size; - } -} - -static const void *fxRunSkip( fxRun_t *run, const fxRunSkip_t *skip ) { - return ((byte *)skip) + skip->size; -} - -static const void *fxRunDistance( fxRun_t *run, const fxRunDistance_t *distance ) { - fxActiveDistance_t *active; - vec3_t delta, realOrigin; - float lengthScale; - - if ( run->entity && run->entity->flags & FX_ENT_STATIONARY ) - return ((byte *)distance) + distance->size; - active = fxGetActive( run->key, (unsigned int)distance, sizeof( fxActiveDistance_t) ); - if ( !active ) - return ((byte *)distance) + distance->size; - if ( !active->beenUsed ) { - active->beenUsed = qtrue; - VectorCopy( run->origin, active->lastOrigin ); - return ((byte *)distance) + distance->size; - } - VectorSubtract( run->origin, active->lastOrigin, delta ); - lengthScale = VectorNormalize( delta ); - if ( lengthScale + active->distance < 0 ) { - return ((byte *)distance) + distance->size; - } - active->distance += lengthScale; - lengthScale = -active->distance; - VectorCopy( run->origin, realOrigin ); - while ( active->distance >= 0 ) { - float step; - const void *mathEnd = fxRunMath( run, distance + 1, &step ); - VectorMA( active->lastOrigin, lengthScale, delta, run->origin ); - lengthScale += step; - active->distance -= step; - fxRun( run, mathEnd ); - } - VectorCopy( realOrigin, active->lastOrigin ); - VectorCopy( realOrigin, run->origin ); - return ((byte *)distance) + distance->size; -} - -static const void *fxRunInterval( fxRun_t *run, const fxRunInterval_t *interval ) { - float i; - fxActiveInterval_t *active; - const void *mathNext; - - active = fxGetActive( run->key, (unsigned int)interval, sizeof( fxActiveInterval_t) ); - if ( !active->beenUsed ) { - mathNext = fxRunMath( run, interval + 1, &i ); - if ( i <= 0) - goto returnIt; - active->beenUsed = qtrue; - fxRun( run, mathNext); - active->nextTime = fx.time + i * 1000; - } else while( active->nextTime <= fx.time ) { - mathNext = fxRunMath( run, interval + 1, &i ); - if ( i <= 0) - break; - fxRun( run, mathNext); - active->nextTime += i * 1000; - } -returnIt: - return ((byte *)interval) + interval->size; - } - -static const void *fxRunOnce( fxRun_t *run, const fxRunOnce_t *once ) { - fxActiveOnce_t *active; - - active = fxGetActive( run->key, (unsigned int)once, sizeof( fxActiveOnce_t) ); - if ( !active->beenUsed ) { - active->beenUsed = qtrue; - fxRun( run, once + 1); - } - return ((byte *)once) + once->size; - } - -static const void *fxRunPushParent( fxRun_t *run, const fxRunPushParent_t *push ) { - int i; - float *input = ( float *)(((char *)(run->parent)) + push->offset); - if ( run->stackUsed + push->count > FX_STACK_SIZE ) { - Com_Printf( "Overflowing run stack\n" ); - return push + 1; - } - for (i = push->count; i > 0; i--) { - run->stackData[run->stackUsed++] = *input++; - } - return push + 1; -} - -static const void *fxRunPush( fxRun_t *run, const fxRunPush_t *push ) { - int i; - float *input = ( float *)(((char *)run) + push->offset); - if ( run->stackUsed + push->count > FX_STACK_SIZE ) { - Com_Printf( "Overflowing run stack\n" ); - return push + 1; - } - for (i = push->count; i > 0; i--) { - run->stackData[run->stackUsed++] = *input++; - } - return push + 1; -} - -static const void *fxRunPop( fxRun_t *run, const fxRunPop_t *pop ) { - int i; - float *output = ( float *)(((char *)run) + pop->offset); - if ( run->stackUsed - pop->count < 0) { - Com_Printf( "underflowing run stack\n" ); - return pop + 1; - } - for (i = pop->count; i > 0; i--) { - output[i-1] = run->stackData[--run->stackUsed]; - } - return pop + 1; -} - -static const void *fxRun( fxRun_t *run, const void *data ); - -static const void *fxRunScript( fxRun_t *run, const fxRunScript_t *script ) { - fxRun( run, script->data ); - return script + 1; -} - -static const void *fxRun( fxRun_t *run, const void *data ) { - while ( 1 ) { - const int *cmdList = (int *)data; - int cmd = cmdList[0]; - data = cmdList + 1; - switch ( cmd ) { - case fxCmdHalt: - return data; - default: - Com_Error( ERR_DROP, "FX:Unknown command %d\n", cmd ); - break; - case fxCmdSkip: - data = fxRunSkip( run, (fxRunSkip_t*)data); - break; - case fxCmdKill: - if ( run->entity ) - run->entity->flags |= FX_ENT_DEAD; - return data; - case fxCmdEmitter: - data = fxRunEmitter( run, (fxRunEmitter_t*)data); - break; - case fxCmdRepeat: - data = fxRunRepeat( run, (fxRunRepeat_t*)data); - break; - case fxCmdDistance: - data = fxRunDistance( run, (fxRunDistance_t*)data); - break; - case fxCmdInterval: - data = fxRunInterval( run, (fxRunInterval_t*)data); - break; - case fxCmdIf: - data = fxRunIf( run, (fxRunIf_t*)data); - break; - case fxCmdOnce: - data = fxRunOnce( run, (fxRunOnce_t*)data); - break; - - case fxCmdLight: - fxRunLight( run ); - break; - case fxCmdSprite: - data = fxRunSprite( run, (fxRunRender_t*)data ); - break; - case fxCmdQuad: - data = fxRunQuad( run, (fxRunRender_t*)data ); - break; - case fxCmdSpark: - data = fxRunSpark( run, (fxRunRender_t*)data ); - break; - case fxCmdBeam: - data = fxRunBeam( run, (fxRunRender_t*)data ); - break; - case fxCmdRings: - data = fxRunRings( run, (fxRunRender_t*)data ); - break; - case fxCmdAxisModel: - data = fxRunAxisModel( run, (fxRunRender_t*)data ); - break; - case fxCmdAnglesModel: - data = fxRunAnglesModel( run, (fxRunRender_t*)data ); - break; - case fxCmdDirModel: - data = fxRunDirModel( run, (fxRunRender_t*)data ); - break; - case fxCmdDecal: - data = fxRunDecal( run, (fxRunDecal_t*)data ); - break; - - case fxCmdTrace: - fxRunTrace( run ); - break; - - case fxCmdScript: - data = fxRunScript( run, (fxRunScript_t*)data ); - break; - case fxCmdColor: - data = fxRunColor( run, (fxRunColor_t*)data); - break; - case fxCmdColorList: - data = fxRunColorList( run, (fxRunColorList_t*)data); - break; - case fxCmdColorBlend: - data = fxRunColorBlend( run, (fxRunColorBlend_t*)data); - break; - case fxCmdColorMath: - data = fxRunColorMath( run, (fxRunColorMath_t*)data); - break; - case fxCmdColorScale: - data = fxRunColorScale( run, data); - break; - case fxCmdColorHue: - data = fxRunColorHue( run, data); - break; - case fxCmdShader: - data = fxRunShader( run, (fxRunShader_t*)data); - break; - case fxCmdShaderList: - data = fxRunShaderList( run, (fxRunShaderList_t*)data); - break; - case fxCmdModel: - data = fxRunModel( run, (fxRunModel_t*)data); - break; - case fxCmdModelList: - data = fxRunModelList( run, (fxRunModelList_t*)data); - break; - case fxCmdSound: - data = fxRunSound( run, (fxRunSound_t*)data); - break; - case fxCmdSoundList: - data = fxRunSoundList( run, (fxRunSoundList_t*)data); - break; - case fxCmdLoopSound: - data = fxRunLoopSound( run, (fxRunLoopSound_t*)data); - break; - case fxCmdVibrate: - data = fxRunVibrate( run, (fxRunVibrate_t*)data); - break; - - case fxCmdAlphaFade: - data = fxRunAlphaFade( run, (fxRunAlphaFade_t*)data); - break; - case fxCmdColorFade: - data = fxRunColorFade( run, (fxRunColorFade_t*)data); - break; - case fxCmdPush: - data = fxRunPush( run, (fxRunPush_t*)data); - break; - case fxCmdPop: - data = fxRunPop( run, (fxRunPop_t*)data); - break; - case fxCmdPushParent: - data = fxRunPushParent( run, (fxRunPushParent_t*)data); - break; - - case fxCmdAdd: - data = fxRunAdd( run, (fxRunAdd_t*)data); - break; - case fxCmdSub: - data = fxRunSub( run, (fxRunSub_t*)data); - break; - case fxCmdAddScale: - data = fxRunAddScale( run, (fxRunAddScale_t*)data); - break; - case fxCmdSubScale: - data = fxRunSubScale( run, (fxRunSubScale_t*)data); - break; - case fxCmdRotateAround: - data = fxRunRotateAround( run, (fxRunRotateAround_t*)data); - break; - case fxCmdScale: - data = fxRunScale( run, (fxRunScale_t*)data); - break; - case fxCmdCopy: - data = fxRunCopy( run, (fxRunCopy_t*)data); - break; - case fxCmdRandom: - data = fxRunRandom( run, (fxRunRandom_t*)data); - break; - case fxCmdWobble: - data = fxRunWobble( run, (fxRunWobble_t*)data); - break; - case fxCmdNormalize: - data = fxRunNormalize( run, (fxRunNormalize_t*)data); - break; - case fxCmdPerpendicular: - data = fxRunPerpendicular( run, (fxRunPerpendicular_t*)data); - break; - case fxCmdInverse: - data = fxRunInverse( run, (fxRunInverse_t*)data); - break; - case fxCmdClear: - data = fxRunClear( run, (fxRunClear_t*)data); - break; - case fxCmdValue: - data = fxRunValue( run, (fxRunValue_t*)data ); - break; - } - } - return data; -} - -static fxEntity_t *fxRunEntities( fxEntity_t **nextEntity ) { - fxEntity_t *lastEntity; - fxRun_t run; - - lastEntity = 0; - for (; nextEntity[0]; nextEntity = &nextEntity[0]->next ) { - float deltaTime; - float moveTime; - int movePasses; - const fxRunEmitter_t *emitter; -killSkip: - run.entity = nextEntity[0]; - - fx.last.entityCount++; - fx.last.entitySize += fxSize( run.entity ); - - deltaTime = (fx.time - run.entity->startTime) + fx.timeFraction; - run.lerp = deltaTime * run.entity->lifeScale; - if ( run.lerp >= 1.0f ) { - run.entity->flags |= FX_ENT_DEAD; - } else if ( deltaTime < 0 ) { - lastEntity = run.entity; - continue; - } - run.shaderTime = run.entity->startTime; - run.life = deltaTime * 0.001; - run.key = (unsigned int)run.entity; - emitter = run.entity->emitter; - run.stackUsed = 0; - - if ( !(emitter->flags & FX_EMIT_MOVE ) ) { - VectorCopy( run.entity->origin, run.origin ); - VectorCopy( run.entity->velocity, run.velocity ); - goto runEntity; - } else if ( !(emitter->flags & FX_EMIT_TRACE ) ) { - VectorMA( run.entity->origin, run.life, run.entity->velocity, run.origin ); - VectorCopy( run.entity->velocity, run.velocity ); - - run.velocity[2] -= 2 * run.life * emitter->gravity; - run.origin[2] -= run.life * run.life * emitter->gravity; - goto runEntity; - } else if ( run.entity->flags & FX_ENT_STATIONARY ) { - VectorCopy( run.entity->origin, run.origin ); - if ( emitter->flags & FX_EMIT_SINK && run.lerp > emitter->sinkDelay ) { - run.origin[2] -= emitter->sinkDepth * ( run.lerp - emitter->sinkDelay ); - } - VectorClear( run.velocity ); - goto runEntity; - } - - moveTime = run.life - run.entity->moveTime; - //Still within the valid trace range just move it directly - if( !moveTime || (moveTime < run.entity->traceTime )) { -traceOkay: - VectorMA( run.entity->origin, moveTime, run.entity->velocity, run.origin ); - run.origin[2] -= moveTime * moveTime * emitter->gravity; - VectorCopy( run.entity->velocity, run.velocity ); - run.velocity[2] -= 2 * moveTime * emitter->gravity; - goto runEntity; - } - - //movepasses will go down fast incase stuff fails - for( movePasses = 2; movePasses >= 0; movePasses-- ) { - trace_t tr; - vec3_t oldOrigin, oldVelocity, newOrigin; - vec3_t traceMin, traceMax; - float addTime; - - //Tracetime holds the time since the last update to the origin/velocity - //Calculate the previous trace end position - VectorMA( run.entity->origin, run.entity->traceTime, run.entity->velocity, oldOrigin ); - oldOrigin[2] -= run.entity->traceTime * run.entity->traceTime * emitter->gravity; - VectorCopy( run.entity->velocity, oldVelocity ); - oldVelocity[2] -= 2 * run.entity->traceTime * emitter->gravity; - - //Predict how far we can go from this position if there's any time left in the particle's life anyway - addTime = 0.001 * movePasses * ( 30 + (rand() & 15 ) ); - - //If the entity is still moving upwards check when upward speed will hit 0 if that takes longer that 2 milliseconds - if ( oldVelocity[2] > 0 ) { - float left = oldVelocity[2] / ( 2 * emitter->gravity ); - if ( left < addTime ) { - addTime = left; - } - traceMin[2] = 0; - traceMax[2] = addTime * addTime * emitter->gravity; - } else { - traceMin[2] = -addTime * addTime * emitter->gravity; - traceMax[2] = 0; - } - traceMin[0] = traceMin[1] = -0.1f; - traceMin[2] -= 0.1f; - traceMax[0] = traceMax[1] = 0.1f; - traceMax[2] += 0.1f; - //Check the end position of the trace without the last piece of gravity - VectorMA( oldOrigin, addTime, oldVelocity, newOrigin ); - - CM_BoxTrace( &tr, oldOrigin, newOrigin, traceMin, traceMax, 0, CONTENTS_SOLID, qfalse ); - if ( tr.allsolid || tr.fraction == 0 ) - break; - if ( tr.fraction < 1 ) { - addTime *= tr.fraction * 0.99; - } - run.entity->traceTime += addTime; - //Have we moved into safe territory for now - if ( run.entity->traceTime >= moveTime ) { - goto traceOkay; - } - //Did we only add a very small piece go into regular trace mode -// if ( addTime > 0.001f ) -// break; - } - - //Can do a few passes if the particle bounces between a few surfaces - for( movePasses = 2; movePasses >= 0; movePasses-- ) { - vec3_t oldOrigin; - trace_t tr; - - VectorMA( run.entity->origin, run.entity->traceTime, run.entity->velocity, oldOrigin ); - oldOrigin[2] -= run.entity->traceTime * run.entity->traceTime * emitter->gravity; - - VectorCopy( run.entity->origin, run.origin ); - VectorMA( run.entity->origin, moveTime, run.entity->velocity, run.origin ); - run.origin[2] -= moveTime * moveTime * emitter->gravity; - - VectorCopy( run.entity->velocity, run.velocity ); - run.velocity[2] -= 2 * moveTime * emitter->gravity; - - //Determine how far we can still go before we hit something - CM_BoxTrace( &tr, oldOrigin, run.origin, vec3_origin, vec3_origin, 0, CONTENTS_SOLID, qtrue ); - if ( tr.allsolid || (tr.surfaceFlags & SURF_NOIMPACT) ) { - /* Special case just don't do anything */ - goto killEntity; - //Full trace succeeded - } else if ( tr.fraction == 1 ) { - goto runEntity; - } else { - if ( emitter->flags & FX_EMIT_IMPACT ) { - run.entity->flags |= FX_ENT_DEAD; - goto runEntity; - } - if ( emitter->impactRun && (VectorLengthSquared( run.velocity ) > emitter->impactSpeed ) ) { - /* Run the optional code for the impact handler */ - VectorCopy( tr.endpos, run.origin ); - VectorCopy( tr.plane.normal, run.dir ); - fxRun( &run, ((char *)emitter) + emitter->impactRun ); - } - if ( emitter->bounceFactor > 0 ) { - float bounceTime; - float reflect; - float fractionTime = ( moveTime - run.entity->traceTime ) * tr.fraction; - - bounceTime = run.entity->traceTime + fractionTime; - if ( tr.fraction ) { - //Add back the velocity till the impact time - run.velocity[2] += 2 * fractionTime * emitter->gravity; - reflect = -2 * DotProduct( tr.plane.normal, run.velocity ); - VectorMA( run.velocity, reflect, tr.plane.normal, run.velocity ); - VectorScale( run.velocity, emitter->bounceFactor, run.velocity ); - VectorCopy( run.velocity, run.entity->velocity ); - } - VectorCopy( tr.endpos, run.entity->origin ); - - //Stop moving if it's on a vertical slope and speed is low */ - if ( ( tr.plane.normal[2] > 0 && VectorLengthSquared( run.velocity ) < 40 ) ) { - run.entity->flags |= FX_ENT_STATIONARY; - VectorClear( run.entity->velocity ); - goto runEntity; - } - //Move slightly back in time to prevent negative offsets - run.entity->moveTime += bounceTime; - moveTime = run.life - run.entity->moveTime; - run.entity->traceTime = 0; - continue; - } - } - } -runEntity: - fxMaskOutput( emitter->mask, run.entity + 1, run.velocity + 3 ); - if ( run.entity->flags & FX_ENT_DEAD ) { - if ( emitter->deathRun ) - fxRun( &run, ((char *)emitter) + emitter->deathRun ); - goto killEntity; - } else { - fxRun( &run, ((char *)emitter) + emitter->emitRun ); - } - lastEntity = run.entity; - continue; -killEntity: - nextEntity[0] = run.entity->next; - fxFree( run.entity ); - if ( !nextEntity[0] ) - break; - goto killSkip; - } - return lastEntity; -} - -static void *fxGetActive( unsigned int key1, unsigned int key2, int size ) { - fxActive_t *active; - unsigned int index; - - index = ((key1 ^ key2) >> FX_ACTIVE_HASH_SHIFT) ^ key1 ^ key2; - index &= FX_ACTIVE_HASH_MASK; - active = fx.activeHash[ index ]; - while (1) { - if (!active) { - active = fxAlloc( sizeof( fxActive_t ) + size ); - if (!active) - return 0; - active->next = fx.activeHash[ index ]; - fx.activeHash[ index ] = active; - - active->key1 = key1; - active->key2 = key2; - memset( active + 1, 0, size ); - fx.last.activeCount++; - fx.last.activeSize += fxSize( active ); - break; - } else if (active->key1 == key1 && active->key2 == key2) { - fx.last.activeCount++; - fx.last.activeSize += fxSize( active ); - break; - } - active = active->next; - } - active->beenUsed = qtrue; - return active + 1; -} - - -static void fxDebugDrawString( int x, int y, const char *line ) { - int i; - for (i = 0; i<40;i++) { - if (!line[i]) - break; - SCR_DrawSmallChar( x, y, line[i] ); - x += SMALLCHAR_WIDTH; - } -} - -static void fxDebugDraw( void ) { - char buf[512]; - int x = cls.glconfig.vidWidth * 3 / 4; - int y = cls.glconfig.vidHeight - SMALLCHAR_HEIGHT * 10 * 1.5; - - re.SetColor( colorWhite ); - - Com_sprintf( buf, sizeof( buf ), "Entities %d, mem %dkb", fx.last.entityCount, fx.last.entitySize / -1024 ); - fxDebugDrawString( x, y, buf ); - y += SMALLCHAR_HEIGHT * 1.5; - Com_sprintf( buf, sizeof( buf ), "Active %d, mem %dkb", fx.last.activeCount, fx.last.activeSize / -1024 ); - fxDebugDrawString( x, y, buf ); - y += SMALLCHAR_HEIGHT * 1.5; - - re.SetColor( NULL ); -} - -void FX_Debug( void ) { - if ( fx_Debug->integer ) - fxDebugDraw(); -} - -void FX_Reset( void ) { - int *lastAlloc; - - memset( fx.activeHash, 0, sizeof( fx.activeHash )); - fx.entityActive = 0; - fx.entityNew = 0; - fx.vibrate.time = 0; - fx.vibrate.used = 0; - /* Create the terminator block */ - fx.allocStart[0] = fx.allocSize - sizeof( int ); - fx.allocSearch = fx.allocStart; - lastAlloc = (int *)(((char *)fx.allocStart) + fx.allocSize - sizeof( int )); - lastAlloc[0] = 0; -} - -void FX_Begin( int time, float timeFraction ) { - fx.deltaTime = fx.time - fx.oldTime; - fx.oldTime = fx.time; - fx.time = time; - fx.timeFraction = timeFraction; - if ( fx.deltaTime < 0 || fx.deltaTime > 50) { - fx.oldTime = fx.time; - fx.deltaTime = 0; - } - fx.seed = time; - /* Clear some stats */ - fx.last.activeCount = 0; - fx.last.entityCount = 0; - fx.last.entitySize = 0; - fx.last.activeSize = 0; - /* Run the currently active entities */ - fxRunEntities( &fx.entityActive ); -} - -void FX_End( void ) { - int i; - int loops = 5; - /* Run all the new entities and loop a few times for recursive entities */ - while ( loops>0 && fx.entityNew ) { - fxEntity_t *newEntities, *lastEntity; - newEntities = fx.entityNew; - fx.entityNew = 0; - lastEntity = fxRunEntities( &newEntities ); - if ( lastEntity ) { - lastEntity->next = fx.entityActive; - fx.entityActive = newEntities; - } - loops --; - } - /* Go through the active list and set all to false */ - for( i = 0; i < FX_ACTIVE_HASH_SIZE; i++) { - fxActive_t **activeList = &fx.activeHash[i]; - while ( activeList[0] ) { - fxActive_t *active = activeList[0]; - if ( active->beenUsed ) { - active->beenUsed = qfalse; - if (!active->next) - break; - activeList = &active->next; - continue; - } - activeList[0] = active->next; - fxFree( active ); - } - } -} - -void FX_Run( fxHandle_t handle, const fxParent_t *parent, unsigned int key ) { - fxRun_t run; - const fxScript_t *script; - - if (handle <= 0 || handle > fx.scriptCount || !parent ) - return; - script = fx.scripts[handle]; - - //Check for illegal readmasks for undefined values - if ( fx_Debug->integer ) { - int debug = fx_Debug->integer; - char warning[256]; - warning[0] = 0; - if ( (script->readMask & FX_MASK_ORIGIN) && !(parent->flags & FXP_ORIGIN ) ) { - Q_strcat( warning, sizeof( warning ), "origin, " ); - } - if ( (script->readMask & FX_MASK_VELOCITY) && !(parent->flags & FXP_VELOCITY ) ) { - Q_strcat( warning, sizeof( warning ), "velocity, " ); - } - if ( (script->readMask & FX_MASK_DIR) && !(parent->flags & FXP_DIR ) ) { - Q_strcat( warning, sizeof( warning ), "dir, " ); - } - if ( (script->readMask & FX_MASK_ANGLES) && !(parent->flags & FXP_ANGLES ) ) { - Q_strcat( warning, sizeof( warning ), "angles, " ); - } - if ( debug > 1 && (script->readMask & FX_MASK_SIZE) && !(parent->flags & FXP_SIZE ) ) { - Q_strcat( warning, sizeof( warning ), "size, " ); - } - if ( (script->readMask & FX_MASK_WIDTH) && !(parent->flags & FXP_WIDTH ) ) { - Q_strcat( warning, sizeof( warning ), "width, " ); - } - if ( debug > 1 && (script->readMask & FX_MASK_SHADER) && !(parent->flags & FXP_SHADER ) ) { - Q_strcat( warning, sizeof( warning ), "shader, " ); - } - if ( (script->readMask & FX_MASK_MODEL) && !(parent->flags & FXP_MODEL ) ) { - Q_strcat( warning, sizeof( warning ), "model, " ); - } - if ( (script->readMask & FX_MASK_AXIS) && !(parent->flags & FXP_AXIS ) ) { - Q_strcat( warning, sizeof( warning ), "axis, " ); - } - if ( warning[0] ) { - Com_Printf("FX_Debug:script '%s' requires %s which aren't supplied by caller\n", script->entry->name, warning ); - } - } - VectorCopy( parent->origin, run.origin ); - if ( parent->flags & FXP_VELOCITY) - VectorCopy( parent->velocity, run.velocity ); - else - VectorClear( run.velocity ); - if ( parent->flags & FXP_DIR ) - VectorCopy( parent->dir, run.dir ); - if ( parent->flags & FXP_ANGLES ) { - VectorCopy( parent->angles, run.angles ); - run.rotate = run.angles[ROLL]; - } else { - VectorClear( run.angles ); - run.rotate = 0; - } - if ( parent->flags & FXP_AXIS ) - AxisCopy( parent->axis, run.axis ); - - *(int *)run.color = ( parent->flags & FXP_COLOR ) ? *(int *)parent->color : 0xffffffff; - run.shader = ( parent->flags & FXP_SHADER ) ? parent->shader : 0; - run.model = ( parent->flags & FXP_MODEL ) ? parent->model : 0; - run.size = ( parent->flags & FXP_SIZE ) ? parent->size : 1.0f; - run.width = ( parent->flags & FXP_WIDTH ) ? parent->width : 1.0f; - - run.parent = parent; - run.shaderTime = 0; - run.key = key; - run.stackUsed = 0; - run.entity = 0; - fxRun( &run, script->data ); -} - - -static void fxList( void ) { - const fxScript_t *script; - int i; - - if ( fx.scriptCount <= 1) { - Com_Printf("No fx scripts loaded\n"); - return; - } - Com_Printf ( "-----------------------\n" ); - for ( i = 1; ientry->name ); - if ( script->remap ) { - Com_Printf( " remap to %s", script->remap->entry->name ); - } - Com_Printf( "\n"); - } - Com_Printf( "%d Total scripts\n", fx.scriptCount - 1); - Com_Printf ( "-----------------------\n" ); -} - -static void fxStats( void ) { - int *alloc = fx.allocStart; - int allocSize, allocBlocks; - int freeSize, freeBlocks; - - allocSize = allocBlocks = 0; - freeSize = freeBlocks = 0; - - while ( 1 ) { - int size = alloc[0]; - if ( size < 0 ) { - size = -size; - allocSize += size; - allocBlocks++; - } else if ( size > 0 ) { - freeSize += size; - freeBlocks++; - } else - break; - alloc = (int*)(((char *)alloc) + size); - } - - Com_Printf( "FX Stats:\n" ); - Com_Printf( "Free %d in %d blocks\n", freeSize, freeBlocks ); - Com_Printf( "Allocated %d in %d blocks\n", allocSize, allocBlocks ); -} - -void FX_Init( void ) { - Com_Memset( &fx, 0, sizeof( fx )); - - fx_Megs = Cvar_Get( "fx_Megs", "2", CVAR_ARCHIVE | CVAR_LATCH ); - fx_Vibrate = Cvar_Get( "fx_Vibrate", "1", CVAR_ARCHIVE ); - fx_Override = Cvar_Get( "fx_Override", "", CVAR_ARCHIVE ); - fx_Debug = Cvar_Get( "fx_Debug", "0", CVAR_CHEAT ); - fx.allocSize = fx_Megs->integer; - if ( fx.allocSize < 1) - fx.allocSize = 1; - else if (fx.allocSize > 8) { - fx.allocSize = 8; - } - fx.allocSize *= 1024*1024; - fx.allocStart = Hunk_Alloc( fx.allocSize, h_low ); - FX_Reset( ); - Cmd_AddCommand( "fxStats", fxStats ); - Cmd_AddCommand( "fxList", fxList ); - Cmd_AddCommand( "fxReset", FX_Reset ); - - fxInitParser(); -} - -void FX_Shutdown( void ) { - Cmd_RemoveCommand( "fxStats" ); - Cmd_RemoveCommand( "fxReset" ); - Cmd_RemoveCommand( "fxRemap" ); - Cmd_RemoveCommand( "fxMath" ); - Cmd_RemoveCommand( "fxReload" ); - if ( fx.alloc.entries ) - fxFreeMemory(); -} \ No newline at end of file diff --git a/code/client/fx_parse.c b/code/client/fx_parse.c deleted file mode 100644 index 23993034..00000000 --- a/code/client/fx_parse.c +++ /dev/null @@ -1,2390 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Sjoerd van der Berg ( harekiet @ gmail.com ) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ - -// fx_parse.c -- Parse and load FX Scripts and handle the fx related math - -#include "client.h" -#include "fx_local.h" - -fxMain_t fx; - -#define parentOfs(m) ((size_t)&((((fxParent_t*)0)->m))) -#define parentSize(m) (sizeof((((fxParent_t*)0)->m)) / sizeof(float)) -#define runOfs(m) ((size_t)&((((fxRun_t*)0)->m))) -#define runSize(m) (sizeof((((fxRun_t*)0)->m)) / sizeof(float)) - -static fxScript_t *fxFindScript( const char *name ); - -static unsigned int fxGenerateHash( const char *name ) { - unsigned int hash = 0; - while (*name) { - char c = tolower(name[0]); - hash = (hash << 5 ) ^ (hash >> 27) ^ c; - name++; - } - return (hash ^ (hash >> FX_HASH_SHIFT) ^ (hash >> (FX_HASH_SHIFT*2))) & FX_HASH_MASK; -} - -typedef enum { - fxParentScript, - fxParentEmitter, -} fxParseParent_t; - -typedef struct { - const char *last, *text, *name, *line; - int lineCount; - char token[1024]; - fxParseParent_t parent; - fxRunEmitter_t *emitter; - int loopDepth; - unsigned int readMask, writeMask, vectorMask; -} fxParse_t; - -typedef struct { - int size, used; - byte *data; -} fxParseOut_t; - - -static ID_INLINE void fxParseWrite( fxParse_t *parse, unsigned int mask ) { - parse->writeMask |= mask; -} - -static ID_INLINE void fxParseRead( fxParse_t *parse, unsigned int mask ) { - mask &= ~parse->writeMask; - parse->readMask |= mask; -} - -qboolean fxParseError( fxParse_t *parse, const char *fmt, ... ) { - va_list argptr; - char msg[512]; - char line[512]; - int i = 0; - - if ( parse->line ) { - while (i < sizeof( line ) - 1) { - if ( !parse->line[i] ) - break; - if ( parse->line[i] == '\n' ) - break; - if ( parse->line[i] == '\r' ) - break; - line[i] = parse->line[i]; - i++; - } - } - line[i] = 0; - - va_start (argptr,fmt); - Q_vsnprintf (msg, sizeof(msg), fmt, argptr); - va_end (argptr); - - Com_Printf( S_COLOR_YELLOW "fxError:'%s' in line '%s' in script '%s'\n", msg ,line, parse->name ); - return qfalse; -} - -qboolean fxParseErrorIllegal( fxParse_t *parse ) { - return fxParseError( parse, "Illegal token %s", parse->token ); -} - -static void *fxParseAlloc( int size ) { - return Z_TagMalloc( size, TAG_FX ); -} -static void fxParseFree( void *free ) { - Z_Free( free ); -} - -static qboolean fxParseCreateMask( fxParse_t *parse, byte *table, int tableLen, unsigned short *allocAdd ) { - byte modMask[ runOfs( stackUsed ) / 4 ]; - unsigned int mask = parse->readMask; - int modeCount, maskIndex, maskLast, tableIndex = 0; - int totalCount; - byte checkVal; - - memset( modMask, 0, sizeof( modMask )); -#define MODSET( m ) memset( modMask + (runOfs( m ) / 4), 1, runSize( m ) ); -#if 0 - if ( mask & FX_MASK_ORIGIN ) MODSET( origin ); - if ( mask & FX_MASK_VELOCITY ) MODSET( velocity ); -#endif - if ( mask & FX_MASK_SHADER ) MODSET( shader ); - if ( mask & FX_MASK_SIZE ) MODSET( size ); - if ( mask & FX_MASK_ROTATE ) MODSET( rotate ); - if ( mask & FX_MASK_COLOR ) MODSET( color ); - - if ( mask & FX_MASK_PARENT ) MODSET( parent ); - if ( mask & FX_MASK_DIR ) MODSET( dir ); - if ( mask & FX_MASK_MODEL ) MODSET( model ); - if ( mask & FX_MASK_AXIS ) MODSET( axis ); - if ( mask & FX_MASK_ANGLES ) MODSET( angles ); - if ( mask & FX_MASK_WIDTH ) MODSET( width ); - if ( mask & FX_MASK_T0 ) MODSET( t0 ); - if ( mask & FX_MASK_T1 ) MODSET( t1 ); - if ( mask & FX_MASK_T2 ) MODSET( t2 ); - if ( mask & FX_MASK_T3 ) MODSET( t3 ); - if ( mask & FX_MASK_V0 ) MODSET( v0 ); - if ( mask & FX_MASK_V1 ) MODSET( v1 ); - if ( mask & FX_MASK_V2 ) MODSET( v2 ); - if ( mask & FX_MASK_V3 ) MODSET( v3 ); -#undef MODSET - - //This is all somewhat hacky, but seems to work - maskIndex = 3 + runOfs( velocity ) / 4; - maskLast = runOfs( parent ) / 4 + runSize( parent ); - modeCount = 0; - totalCount = 0; - checkVal = 0; - - while ( maskIndex < maskLast ) { - if ( checkVal == modMask[maskIndex] ) { - maskIndex++; - modeCount++; - totalCount += checkVal; - } else { - if ( tableIndex >= tableLen ) - return fxParseError( parse, "Ran out of write mask space" ); - checkVal ^= 1; - table[tableIndex++] = modeCount; - modeCount = 0; - } - } - if ( tableIndex >= tableLen ) - return fxParseError( parse, "Ran out of write mask space" ); - table[tableIndex++] = modeCount; - if (modeCount) { - if ( tableIndex >= tableLen ) - return fxParseError( parse, "Ran out of write mask space" ); - table[tableIndex++] = 0; - } - *allocAdd += totalCount * 4; - return qtrue; -} - -#define SEPERATOR(_T_) ((_T_ == ' ') || (_T_ == '\n') || (_T_ == '\t') || (_T_ == '\r')) - -static qboolean fxParseToken( fxParse_t *parse, qboolean skipLine ) { - const char *p = parse->text; - char *token = parse->token; - qboolean haveQuote = qfalse; - int tokenLength = 0; - - if (!parse->line) - parse->line = p; - - parse->last = p; - while (1) { - if ( tokenLength >= sizeof( parse->token )) { - parse->token[ sizeof( parse->token ) -1 ] = 0; - return fxParseError( parse, "token %s too long", parse->token ); - } - if ( haveQuote ) { - if (*p == '\n' || *p == '\r' || *p == 0) { - return fxParseError( parse, "token missing end quote" ); - } - if ( *p == '\"' ) { - if (!SEPERATOR(p[1]) && !p[1]) - return fxParseError( parse, "token quote followed by a character" ); - haveQuote = qfalse; - p++; - break; - } - token[tokenLength++] = p[0]; - } else if ( tokenLength ) { - if (SEPERATOR(p[0]) || !p[0]) - break; - token[tokenLength++] = p[0]; - } else if (!p[0]) { - break; - } else if (p[0] == '"' ) { - haveQuote = qtrue; - } else if (SEPERATOR(p[0])) { - if ( p[0] == '\n' || p[0] == '\r' ) { - if ( !skipLine ) - break; - parse->line = p+1; - parse->last = 0; - } - } else { - token[tokenLength++] = p[0]; - } - p++; - } - parse->text = p; - token[tokenLength] = 0; - if (!tokenLength ) - return qfalse; - return qtrue; -} - -static qboolean fxParseReverse( fxParse_t *parse ) { - if (!parse->last) - return fxParseError( parse, "Can't reverse a token" ); - parse->text = parse->last; - return qtrue; -} - -static qboolean fxParseWord( fxParse_t *parse, const char *type ) { - if (!fxParseToken( parse, qfalse )) { - if ( !type ) - type = "word"; - return fxParseError( parse, "Missing %s" ); - } - return qtrue; -} - -static qboolean fxParseCompare( fxParse_t *parse, const char *compare ) { - if (!fxParseWord( parse, compare )) { - return qfalse; - } - if (Q_stricmp( parse->token, compare )) - return fxParseError( parse, "%s doesn't match %s", parse->token, compare ); - return qtrue; -} - -typedef qboolean (*fxListMatch_t)( fxParse_t *, void * ); - -static qboolean fxParseList( fxParse_t *parse, const char *list, fxListMatch_t match, int dataSize, void *data, int countMax, unsigned int *count ) { - const char *token = parse->token; - - if (!fxParseCompare( parse, "{")) - return qfalse; - *count = 0; - while ( 1 ) { - if (!fxParseToken( parse, qtrue )) { - return fxParseError( parse, "Expected %s entry", list ); - } - if (!Q_stricmp( token, "}")) - break; - if (!match( parse, ((char *)data) + *count * dataSize )) - return qfalse; - (*count)++; - if ( *count >= countMax ) - return fxParseError( parse, "Too many entries for %s (max %d)", list, countMax ); - } - if (!*count) - return fxParseError( parse, "%s is empty", list ); - return qtrue; -} - -static qboolean fxMatchValidFloat( fxParse_t *parse ) { - int doneNumber = 0; - int donePoint = 0; - - char *token = parse->token; - for ( ;1;token++) { - switch (*token) { - case 0: - if (!doneNumber) - return fxParseError( parse, "empty float", parse->token ); - return qtrue; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - doneNumber++; - continue; - case '.': - if ( donePoint ) - return fxParseError( parse, "invalid float %s", parse->token ); - donePoint++; - continue; - default: - return fxParseError( parse, "illegal char %c in float %s", *token, parse->token ); - } - } - return qfalse; -} - -static qboolean fxParseFloat( fxParse_t *parse, float *data ) { - if (!fxParseToken( parse, qfalse )) { - return fxParseError( parse, "Expected float" ); - } - if (!fxMatchValidFloat( parse )) - return qfalse; - //TODO check for valid float? - *data = atof( parse->token ); - return qtrue; -} - -/* Bit of a hack to parse the second 2 values */ -static qboolean fxMatchColor( fxParse_t *parse, byte *data ) { - int i; - for (i = 0;i<3;i++) { - float f; - if (!i) { - if (!fxMatchValidFloat( parse )) - return qfalse; - f = atof( parse->token ); - } else if (!fxParseFloat( parse, &f)) { - return qfalse; - } - if ( f < 0 ) - f = 0; - else if ( f > 1) - f = 1; - data[i] = f * 255; - } - return qtrue; -} - -static qboolean fxMatchShader( fxParse_t *parse, qhandle_t *data ) { - data[0] = re.RegisterShader( parse->token ); - if (!data[0]) - return fxParseError( parse, "shader %s not found", parse->token ); - return qtrue; -} - -static qboolean fxMatchModel( fxParse_t *parse, qhandle_t *data ) { - data[0] = re.RegisterModel( parse->token ); - if (!data[0]) - return fxParseError( parse, "model %s not found", parse->token ); - return qtrue; -} - -static qboolean fxMatchSound( fxParse_t *parse, sfxHandle_t *data ) { - data[0] = S_RegisterSound( parse->token, qfalse ); - if (!data[0]) - return fxParseError( parse, "Sound %s not found", parse->token ); - return qtrue; -} - -static qboolean fxParseColor( fxParse_t *parse, byte *data ) { - int i; - for (i = 0;i<3;i++) { - float f; - if (!fxParseFloat( parse, &f )) { - return qfalse; - } - if ( f < 0 ) - f = 0; - else if ( f > 1) - f = 1; - data[i] = f * 255; - } - return qtrue; -} - -static qboolean fxParseRenderFX( fxParse_t *parse, int *renderFX ) { - *renderFX = RF_NOSHADOW; - while (fxParseToken( parse, qfalse ) ) { - const char *token = parse->token; - if (!Q_stricmp(token, "firstPerson")) { - *renderFX |= RF_FIRST_PERSON; - } else if (!Q_stricmp(token, "thirdPerson")) { - *renderFX |= RF_THIRD_PERSON; - } else if (!Q_stricmp(token, "shadow")) { - *renderFX &= ~RF_NOSHADOW; - } else if (!Q_stricmp(token, "cullNear") || !Q_stricmp(token, "cullRadius" ) ) { - *renderFX |= RF_CULLRADIUS; - } else if (!Q_stricmp(token, "depthHack")) { - *renderFX |= RF_DEPTHHACK; - } else if (!Q_stricmp(token, "stencil")) { - *renderFX |= RF_STENCIL; - } else { - return fxParseError( parse, "Illegal render keyword %s", token ); - } - } - return qtrue; -} - - -static qboolean fxParseOut( fxParse_t *parse, fxParseOut_t *out, const void *data, int size ) { - if ( out->used + size + sizeof( void *) > out->size ) { - fxParseError( parse, "Overflowing output buffer" ); - return qfalse; - } - memcpy( out->data + out->used, data, size ); - out->used += size; - return qtrue; -} - -static qboolean fxParseOutCmd( fxParse_t *parse, fxParseOut_t *out, int cmd, const void *data, int size ) { - if (!fxParseOut( parse, out, &cmd, sizeof( cmd ) )) - return qfalse; - if (!fxParseOut( parse, out, data, size )) - return qfalse; - return qtrue; -} - -typedef struct { - fxRun_t *run; - const int *data; -} fxMathInfo_t; - -typedef float (*fxMathHandler)( fxMathInfo_t *info ); - -static float ID_INLINE fxMath( fxMathInfo_t *info ) { - fxMathHandler * handler = ( fxMathHandler *)info->data; - info->data++; - return (*handler)( info ); -} - -const void *fxRunMath( fxRun_t *run, const void *data, float *value ) { - fxMathInfo_t info; - info.run = run; - info.data = data; - - *value = fxMath( &info ); - return info.data; -} -static float fxMathNeg( fxMathInfo_t *info ) { - return -fxMath( info ); -} -static float fxMathMul( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return v1 * v2; -} -static float fxMathDiv( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return v1 / v2; -} -static float fxMathAdd( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return v1 + v2; -} -static float fxMathSub( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return v1 - v2; -} - -static float fxMathEqual( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return ((v1 != 0) == (v2 != 0)) ? 1 : 0; -} -static float fxMathNotEqual( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return ((v1 != 0) != (v2 != 0)) ? 1 : 0; -} - -static float fxMathTE( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return ( v1 == v2 ) ? 1 : 0; -} -static float fxMathTNE( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return ( v1 != v2 ) ? 1 : 0; -} -static float fxMathTG( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 > v2) ? 1 : 0; -} -static float fxMathTGE( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 >= v2) ? 1 : 0; -} -static float fxMathTS( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 < v2) ? 1 : 0; -} -static float fxMathTSE( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 <= v2) ? 1 : 0; -} - -static float fxMathAND( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 && v2) ? 1 : 0; -} - -static float fxMathOR( fxMathInfo_t *info ) { - float v1 = fxMath( info ); - float v2 = fxMath( info ); - return (v1 || v2) ? 1 : 0; -} - -static float fxMathSin( fxMathInfo_t *info ) { - return sinf( DEG2RAD( fxMath( info ))); -} -static float fxMathCos( fxMathInfo_t *info ) { - return cosf( DEG2RAD( fxMath( info ))); -} -static float fxMathWave( fxMathInfo_t *info ) { - return sinf( fxMath( info ) * 2 * M_PI ); -} -static float fxMathSqrt( fxMathInfo_t *info ) { - return sqrtf( fxMath( info )); -} -static float fxMathCeil( fxMathInfo_t *info ) { - return ceilf( fxMath( info )); -} -static float fxMathFloor( fxMathInfo_t *info ) { - return floorf( fxMath( info )); -} -static float fxMathClip( fxMathInfo_t *info) { - float v = fxMath( info ); - if ( v < 0.0f) - return 0.0f; - if ( v > 1.0f ) - return 1.0f; - return v; -} -static float fxMathZero( fxMathInfo_t *info ) { - return 0; -} -static float fxMathPi( fxMathInfo_t *info ) { - return M_PI; -} -static float fxMathRed( fxMathInfo_t *info ) { - return info->run->color[0] * (1.0f/255); -} -static float fxMathGreen( fxMathInfo_t *info ) { - return info->run->color[1] * (1.0f/255); -} -static float fxMathBlue( fxMathInfo_t *info ) { - return info->run->color[2] * (1.0f/255); -} -static float fxMathAlpha( fxMathInfo_t *info ) { - return info->run->color[3] * (1.0f/255); -} -static float fxMathValue( fxMathInfo_t *info ) { - int ofs = info->data[0]; - float *v = (float *)(((char *)info->run) + ofs); - info->data++; - return v[0]; -} -static float fxMathLength( fxMathInfo_t *info ) { - int ofs = info->data[0]; - const float *v = fxFloatSrc( info->run, ofs ); - info->data++; - return VectorLength( v ); -} -static float fxMathParent( fxMathInfo_t *info ) { - int ofs = info->data[0]; - float *v = (float *)(((char *)info->run->parent) + ofs); - info->data++; - return v[0]; -} -static float fxMathConst( fxMathInfo_t *info) { - float v1 = ((float *)info->data)[0]; - info->data++; - return v1; -} -static float fxMathTime( fxMathInfo_t *info) { - return fx.time * 0.001f; -} -static float fxMathRand( fxMathInfo_t *info) { - fx.seed = fx.seed * 16091 + 1; - return (fx.seed & 0xffff) * (1.0f / 0x10000); -} -static float fxMathCrand( fxMathInfo_t *info) { - fx.seed = fx.seed * 16091 + 1; - return 1.0f - (2.0f / 0x10000) * (fx.seed & 0xffff); -} -static float fxMathCvar( fxMathInfo_t *info ) { - cvar_t *cvar; - memcpy( &cvar, info->data, sizeof( cvar_t *)); - info->data += sizeof( cvar_t *) / sizeof( int ); - return cvar->value; -} - -static qboolean fxParseParentValue( const char *val, int *ofs ) { - if (0) { - } else if (!Q_stricmp( val, "parentorigin0")) { - *ofs = parentOfs( origin[0] ); - } else if (!Q_stricmp( val, "parentorigin1")) { - *ofs = parentOfs( origin[1] ); - } else if (!Q_stricmp( val, "parentorigin2")) { - *ofs = parentOfs( origin[2] ); - } else if (!Q_stricmp( val, "parentvelocity0")) { - *ofs = parentOfs( velocity[0] ); - } else if (!Q_stricmp( val, "parentvelocity1")) { - *ofs = parentOfs( velocity[1] ); - } else if (!Q_stricmp( val, "parentvelocity2")) { - *ofs = parentOfs( velocity[2] ); - } else if (!Q_stricmp( val, "parentangles0")) { - *ofs = parentOfs( angles[0] ); - } else if (!Q_stricmp( val, "parentangles1")) { - *ofs = parentOfs( angles[1] ); - } else if (!Q_stricmp( val, "parentangles2")) { - *ofs = parentOfs( angles[2] ); - } else if (!Q_stricmp( val, "parentyaw")) { - *ofs = parentOfs( angles[YAW] ); - } else if (!Q_stricmp( val, "parentpitch")) { - *ofs = parentOfs( angles[PITCH] ); - } else if (!Q_stricmp( val, "parentroll")) { - *ofs = parentOfs( angles[ROLL] ); - } else if (!Q_stricmp( val, "parentangle")) { - *ofs = parentOfs( angles[ROLL] ); - } else if (!Q_stricmp( val, "parentsize")) { - *ofs = parentOfs( size ); - } else { - return qfalse; - } - return qtrue; -} - - -#define PARSE_RUN_VECTOR_ENTRY( _VEC, _MASK, _NUM ) \ - if (!Q_stricmp( val, #_VEC #_NUM)) { \ - *ofs = runOfs( _VEC[_NUM] ); \ - *mask = _MASK; \ - } - - -#define PARSE_RUN_VECTOR( _VEC, _MASK ) \ - PARSE_RUN_VECTOR_ENTRY( _VEC, _MASK, 0 ) \ - else \ - PARSE_RUN_VECTOR_ENTRY( _VEC, _MASK, 1 ) \ - else \ - PARSE_RUN_VECTOR_ENTRY( _VEC, _MASK, 2 ) - - -static qboolean fxMatchFloat( const char *val, int *ofs, unsigned int *mask ) { - PARSE_RUN_VECTOR( origin, FX_MASK_ORIGIN ) - else PARSE_RUN_VECTOR( velocity, FX_MASK_VELOCITY ) - else PARSE_RUN_VECTOR( angles, FX_MASK_ANGLES ) - else PARSE_RUN_VECTOR( dir, FX_MASK_DIR ) - else PARSE_RUN_VECTOR( v0, FX_MASK_V0 ) - else PARSE_RUN_VECTOR( v1, FX_MASK_V1 ) - else PARSE_RUN_VECTOR( v2, FX_MASK_V2 ) - else PARSE_RUN_VECTOR( v3, FX_MASK_V3 ) - else if (!Q_stricmp( val, "rotate") || !Q_stricmp( val, "angle")) { - *ofs = runOfs( rotate ); - *mask = FX_MASK_ROTATE; - } else if (!Q_stricmp( val, "size")) { - *ofs = runOfs( size ); - *mask = FX_MASK_SIZE; - } else if (!Q_stricmp( val, "width")) { - *ofs = runOfs( width ); - *mask = FX_MASK_WIDTH; - } else if (!Q_stricmp( val, "yaw")) { - *ofs = runOfs( angles[YAW] ); - *mask = FX_MASK_ANGLES; - } else if (!Q_stricmp( val, "pitch")) { - *ofs = runOfs( angles[PITCH] ); - *mask = FX_MASK_ANGLES; - } else if (!Q_stricmp( val, "roll")) { - *ofs = runOfs( angles[ROLL] ); - *mask = FX_MASK_ANGLES; - } else if (!Q_stricmp( val, "t0")) { - *ofs = runOfs( t0 ); - *mask = FX_MASK_T0; - } else if (!Q_stricmp( val, "t1")) { - *ofs = runOfs( t1 ); - *mask = FX_MASK_T1; - } else if (!Q_stricmp( val, "t2")) { - *ofs = runOfs( t2 ); - *mask = FX_MASK_T2; - } else if (!Q_stricmp( val, "t3")) { - *ofs = runOfs( t3 ); - *mask = FX_MASK_T3; - } else { - return qfalse; - } - return qtrue; -} - -static qboolean fxMatchVector( const char *val, int *ofs, unsigned int *mask ) { - if (!Q_stricmp( val, "origin")) { - *ofs = runOfs( origin ); - *mask = FX_MASK_ORIGIN; - } else if (!Q_stricmp( val, "velocity")) { - *ofs = runOfs( velocity ); - *mask = FX_MASK_VELOCITY; - } else if (!Q_stricmp( val, "angles")) { - *ofs = runOfs( angles ); - *mask = FX_MASK_ANGLES; - } else if (!Q_stricmp( val, "dir")) { - *ofs = runOfs( dir ); - *mask = FX_MASK_DIR; - } else if (!Q_stricmp( val, "v0")) { - *ofs = runOfs( v0 ); - *mask = FX_MASK_V0; - } else if (!Q_stricmp( val, "v1")) { - *ofs = runOfs( v1 ); - *mask = FX_MASK_V1; - } else if (!Q_stricmp( val, "v2")) { - *ofs = runOfs( v2 ); - *mask = FX_MASK_V2; - } else if (!Q_stricmp( val, "v3")) { - *ofs = runOfs( v3 ); - *mask = FX_MASK_V3; - } else if (!Q_stricmp( val, "parentOrigin" )) { - *ofs = parentOfs( origin ) | FX_VECTOR_PARENT; - *mask = FX_MASK_PARENT; - } else if (!Q_stricmp( val, "parentVelocity" )) { - *ofs = parentOfs( velocity ) | FX_VECTOR_PARENT; - *mask = FX_MASK_PARENT; - } else if (!Q_stricmp( val, "parentAngles" )) { - *ofs = parentOfs( angles ) | FX_VECTOR_PARENT; - *mask = FX_MASK_PARENT; - } else if (!Q_stricmp( val, "parentDir" )) { - *ofs = parentOfs( dir ) | FX_VECTOR_PARENT; - *mask = FX_MASK_PARENT; - } else { - return qfalse; - } - return qtrue; -} - -static qboolean fxParseVectorOptional( fxParse_t *parse, int *ofs ) { - unsigned int mask; - - if (!fxParseToken( parse, qfalse )) { - mask = parse->vectorMask; - } else if (!fxMatchVector( parse->token, ofs, &mask ) ) { - mask = parse->vectorMask; - if (!fxParseReverse( parse )) - return qfalse; - } - if ( mask & FX_MASK_PARENT ) { - return fxParseError( parse, "Can't write to a parent vector" ); - } - fxParseWrite( parse, mask ); - return qtrue; -} - -static qboolean fxParseVectorRead( fxParse_t *parse, int *ofs ) { - unsigned int mask; - if (!fxParseToken( parse, qfalse )) { - return fxParseError( parse, "Expected read vector name" ); - } - if ( !fxMatchVector( parse->token, ofs, &mask ) ) { - return fxParseError( parse, "Unknown read vector name %s", parse->token ); - } - parse->vectorMask = mask; - fxParseRead( parse, mask ); - return qtrue; -} - -static qboolean fxParseVectorWrite( fxParse_t *parse, int *ofs ) { - unsigned int mask; - if (!fxParseToken( parse, qfalse )) { - return fxParseError( parse, "Expected write vector name" ); - } - if ( !fxMatchVector( parse->token, ofs, &mask ) ) { - return fxParseError( parse, "Unknown write vector name %s", parse->token ); - } - if ( mask & FX_MASK_PARENT ) { - return fxParseError( parse, "Can't write to a parent vector" ); - } - fxParseWrite( parse, mask ); - return qtrue; -} - -typedef enum { - mathParseLine, - mathParseSingle, - mathParseMul, -} mathParseType_t; - -typedef struct { - byte data[1024]; - int used; -} fxMathOut_t; - - -static qboolean fxMathAppend( fxParse_t *parse, fxMathOut_t *out, const void *data, int size ) { - if ( size + out->used > sizeof( out->data )) - return fxParseError( parse, "Overflowing math parser" ); - if ( !size || !data) - return fxParseError( parse, "math adding 0 sized data" ); - memcpy( out->data + out->used, data, size ); - out->used += size; - return qtrue; -} - -static qboolean fxMathAppendOut( fxParse_t *parse, fxMathOut_t *out, const fxMathOut_t *add ) { - return fxMathAppend( parse, out, add->data, add->used ); -} - -static qboolean fxMathAppendInt( fxParse_t *parse, fxMathOut_t *out, int val ) { - return fxMathAppend( parse, out, &val, sizeof( int )); -} - -static qboolean fxMathAppendHandler( fxParse_t *parse, fxMathOut_t *out, fxMathHandler handler ) { - //TODO for 64bit platforms use a relative 32bit offset - return fxMathAppend( parse, out, &handler, sizeof( handler )); -} - -static qboolean fxMathParse( fxParse_t *parse, mathParseType_t parseType, char **line, const fxMathOut_t *in, fxMathOut_t *out ); - -static qboolean fxMathParseHandler( fxParse_t *parse, char **line, fxMathOut_t *out, fxMathHandler handler ) { - if (!fxMathAppendHandler( parse, out, handler)) - return qfalse; - return fxMathParse( parse, mathParseSingle, line, 0, out ); -} - - -static qboolean fxMathParse( fxParse_t *parse, mathParseType_t parseType, char **line, const fxMathOut_t *in, fxMathOut_t *out ) { - char buf[64]; - int wordSize; - fxMathOut_t val; - fxMathHandler tempHandler; - - wordSize = 0; - val.used = 0; - - if ( parseType == mathParseLine && !in ) { - if (!fxMathParse( parse, mathParseMul, line, 0, &val )) - return qfalse; - return fxMathParse( parse, mathParseLine, line, &val, out ); - } - - while ( 1 ) { - char c = line[0][0]; - - if ( wordSize ) { - int i; - qboolean isNumber; - - if ( !c || c == ')' || c == '(' || c == ' ' - || c == '-' || c =='+' || c == '*' || c == '/' - || c == '!' || c == '<' || c == '>' || c == '=' || - c == '&' || c == '|' ) { - /* Easier to just parse the value first incase of trouble */ - buf[wordSize] = 0; - - if ( val.used ) - return fxParseError( parse, "math double value %s", buf ); - - isNumber = qtrue; - for ( i = 0; i < wordSize;i++) { - if (!(buf[i] == '.' || (buf[i] >= '0' && buf[i] <= '9'))) { - isNumber = qfalse; - break; - } - } - - if ( isNumber ) { - float value = atof( buf ); - if (!fxMathAppendHandler( parse, &val, fxMathConst )) - return qfalse; - if (!fxMathAppend( parse, &val, &value, sizeof( value ))) - return qfalse; - } else if (!Q_stricmp( buf, "sin")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathSin )) - return qfalse; - } else if (!Q_stricmp( buf, "cos")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathCos )) - return qfalse; - } else if (!Q_stricmp( buf, "wave")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathWave)) - return qfalse; - } else if (!Q_stricmp( buf, "sqrt")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathSqrt )) - return qfalse; - } else if (!Q_stricmp( buf, "ceil")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathCeil )) - return qfalse; - } else if (!Q_stricmp( buf, "floor")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathFloor )) - return qfalse; - } else if (!Q_stricmp( buf, "clip")) { - if (!fxMathParseHandler( parse, line, &val, &fxMathClip )) - return qfalse; - } else if (!Q_stricmp( buf, "rand") || !Q_stricmp( buf, "rnd")) { - if (!fxMathAppendHandler( parse, &val, &fxMathRand)) - return qfalse; - } else if (!Q_stricmp( buf, "time")) { - if (!fxMathAppendHandler( parse, &val, &fxMathTime)) - return qfalse; - } else if (!Q_stricmp( buf, "crand")) { - if (!fxMathAppendHandler( parse, &val, &fxMathCrand)) - return qfalse; - } else if (!Q_stricmp( buf, "pi")) { - if (!fxMathAppendHandler( parse, &val, &fxMathPi)) - return qfalse; - } else if (!Q_stricmp( buf, "red")) { - if (!fxMathAppendHandler( parse, &val, &fxMathRed)) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR); - } else if (!Q_stricmp( buf, "green")) { - if (!fxMathAppendHandler( parse, &val, &fxMathGreen)) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR); - } else if (!Q_stricmp( buf, "blue")) { - if (!fxMathAppendHandler( parse, &val, &fxMathBlue)) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR); - } else if (!Q_stricmp( buf, "alpha")) { - if (!fxMathAppendHandler( parse, &val, &fxMathAlpha)) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR); - } else if (!Q_stricmp( buf, "life")) { - if ( !parse->emitter ) - return fxParseError( parse, "Can't access life outside of emitter" ); - if (!fxMathAppendHandler( parse, &val, &fxMathValue)) - return qfalse; - if (!fxMathAppendInt( parse, &val, runOfs( life ))) - return qfalse; - } else if (!Q_stricmp( buf, "lerp")) { - if ( !parse->emitter ) - return fxParseError( parse, "Can't access lerp outside of emitter" ); - if (!fxMathAppendHandler( parse, &val, &fxMathValue)) - return qfalse; - if (!fxMathAppendInt( parse, &val, runOfs( lerp ))) - return qfalse; - } else if (!Q_stricmp( buf, "loop")) { - if ( parse->loopDepth <= 0 ) - return fxParseError( parse, "Can't access loop outside of a loop" ); - if (!fxMathAppendHandler( parse, &val, &fxMathValue)) - return qfalse; - if (!fxMathAppendInt( parse, &val, runOfs( loop ))) - return qfalse; - } else { - int ofs; - unsigned int mask; - cvar_t *cv; - if (fxMatchFloat( buf, &ofs, &mask)) { - parse->readMask |= mask; - if (!fxMathAppendHandler( parse, &val, fxMathValue)) - return qfalse; - if (!fxMathAppendInt( parse, &val, ofs )) - return qfalse; - } else if (fxMatchVector( buf, &ofs, &mask)) { - parse->readMask |= mask; - if (!fxMathAppendHandler( parse, &val, fxMathLength)) - return qfalse; - if (!fxMathAppendInt( parse, &val, ofs )) - return qfalse; - } else if (fxParseParentValue( buf, &ofs)) { - parse->readMask |= FX_MASK_PARENT; - if (!fxMathAppendHandler( parse, &val, fxMathParent)) - return qfalse; - if (!fxMathAppendInt( parse, &val, ofs )) - return qfalse; - } else if ( (cv = Cvar_FindVar( buf )) ) { - if (!fxMathAppendHandler( parse, &val, &fxMathCvar)) - return qfalse; - if (!fxMathAppend( parse, &val, &cv, sizeof( cv ))) - return qfalse; - } else { - return fxParseError( parse, "math unknown word %s", buf ); - } - } - wordSize = 0; - } else { - if (wordSize >= sizeof( buf ) - 1) - return fxParseError( parse, "math too long word %s", buf ); - buf[wordSize++] = c; - line[0]++; - } - continue; - } - - switch (c) { - case '+': - case '-': - if ( parseType != mathParseLine ) { - if ( val.used ) - return fxMathAppendOut( parse, out, &val ); - if ( c == '-' && !fxMathAppendHandler( parse, out, fxMathNeg )) - return qfalse; - line[0]++; - return fxMathParse( parse, mathParseMul, line, 0, out ); - } - line[0]++; - if (!fxMathAppendHandler( parse, &val, c == '+' ? fxMathAdd : fxMathSub )) - return qfalse; - if (!fxMathAppendOut( parse, &val, in )) - return qfalse; - if (!fxMathParse( parse, mathParseMul, line, 0, &val )) - return qfalse; - return fxMathParse( parse, mathParseLine, line, &val, out ); - case '!': - case '<': - case '>': - case '=': - case '&': - case '|': - if ( parseType != mathParseLine ) { - if (!val.used ) - return fxParseError( parse, "Expected value before %c", c ); - return fxMathAppendOut( parse, out, &val ); - } - switch (c) { - case '&': - if ( line[0][1] == '&' ) - line[0]++; - tempHandler = fxMathAND; - break; - case '|': - if ( line[0][1] == '|' ) - line[0]++; - tempHandler = fxMathOR; - break; - case '<': - if ( line[0][1] == '=' ) { - line[0]++; - tempHandler = fxMathTSE; - } else { - tempHandler = fxMathTS; - } - break; - case '>': - if ( line[0][1] == '=' ) { - line[0]++; - tempHandler = fxMathTGE; - } else { - tempHandler = fxMathTG; - } - break; - case '!': - if ( line[0][1] == '=' ) { - line[0]++; - tempHandler = fxMathNotEqual; - } else { - tempHandler = fxMathTNE; - } - break; - case '=': - if ( line[0][1] == '=' ) { - line[0]++; - tempHandler = fxMathEqual; - } else { - tempHandler = fxMathTE; - } - break; - default: - return fxParseError( parse, "math unknown char '%c'", c ); - } - line[0]++; - if (!fxMathAppendHandler( parse, out, tempHandler )) - return qfalse; - if (!fxMathAppendOut( parse, out, in )) - return qfalse; - return fxMathParse( parse, mathParseLine, line, 0, out ); - case '*': - case '/': - if (!val.used) { - return fxParseError( parse, "math unexpected %c", c ); - } - if ( parseType != mathParseMul ) - return fxMathAppendOut( parse, out, &val ); - line[0]++; - if (!fxMathAppendHandler( parse, out, c == '*' ? fxMathMul : fxMathDiv )) - return qfalse; - if (!fxMathAppendOut( parse, out, &val )) - return qfalse; - return fxMathParse( parse, mathParseMul, line, 0, out ); - case '(': - if ( val.used || parseType == mathParseLine) - return fxParseError( parse, "math unexpected (" ); - line[0]++; - if (!fxMathParse( parse, mathParseLine, line, 0, &val )) - return qfalse; - if (line[0][0] != ')' ) - return fxParseError( parse, "math expected )" ); - line[0]++; - continue; - case ')': - if ( parseType == mathParseLine ) { - if (!in || !in->used ) - return fxParseError( parse, "math:unexpected )"); - return fxMathAppendOut( parse, out, in ); - } - return fxMathAppendOut( parse, out, &val ); - case 0: - if ( parseType == mathParseLine ) { - if (!in ) - return fxParseError( parse, "math empty line?" ); - return fxMathAppendOut( parse, out, in ); - } - if ( !val.used ) - return fxParseError( parse, "math expected some value" ); - return fxMathAppendOut( parse, out, &val ); - case ' ': - line[0]++; - continue; - default: - if ( val.used ) - return fxParseError( parse, "math unexpected char %c", c ); - buf[wordSize++] = c; - line[0]++; - continue; - } - //Final break that only reaches when we end this parse - break; - } - return qfalse; -} - -static qboolean fxParseMath( fxParse_t *parse, fxParseOut_t *out ) { - char buf[1024]; - int i; - const char *p; - char *line; - fxMathOut_t mathOut; - - p = parse->text; - parse->last = p; - i = 0; - - for( ;; p++ ) { - switch (*p) { - case '\n': - case '\r': - case '{': - case 0: - break; - case '"': - continue; - default: - if ( i > sizeof( buf) - 2) - break; - buf[i++] = *p; - continue; - } - break; - } - parse->text = p; - buf[i] = 0; - - line = buf; - mathOut.used = 0; - if (!fxMathParse( parse, mathParseLine, &line, 0, &mathOut )) - return qfalse; - if ( out->used + mathOut.used > out->size ) - return fxParseError( parse, "Overflowing output buffer" ); - memcpy( out->data + out->used, mathOut.data, mathOut.used ); - out->used += mathOut.used; - return qtrue; -} - -static qboolean fxParseStackName( fxParse_t *parse, int *ofs, int *count, unsigned int *mask ) { - - const char *token = parse->token; - if (!fxParseWord( parse , "stack name" )) - return qfalse; - - if ( fxMatchFloat( token, ofs, mask )) { - *count = 1; - return qtrue; - } else if ( fxMatchVector( token, ofs, mask )) { - if ( *mask & FX_MASK_PARENT ) - return fxParseError( parse, "Can't access parent value %s", token ); - *count = 3; - return qtrue; - } else if (!Q_stricmp( token, "color")) { - *ofs = runOfs( color ); - *count = runSize( color ); - *mask = FX_MASK_COLOR; - } else if (!Q_stricmp( token, "model")) { - *ofs = runOfs( model ); - *count = runSize( model ); - *mask = FX_MASK_MODEL; - } else if (!Q_stricmp( token, "shader")) { - *ofs = runOfs( shader ); - *count = runSize( shader ); - *mask = FX_MASK_SHADER; - } else { - return fxParseError( parse, "Unknown stack tag %s", token ); - } - return qtrue; -} - -static qboolean fxParseParentName( fxParse_t *parse, int *ofs, int *count ) { - const char *token = parse->token; - if (!fxParseWord( parse, "parentname" )) - return qfalse; - if (!Q_stricmp( token, "origin")) { - *ofs = parentOfs( origin ); - *count = parentSize( origin ); - } else if (!Q_stricmp( token, "velocity")) { - *ofs = parentOfs( velocity ); - *count = parentSize( velocity ); - } else if (!Q_stricmp( token, "dir")) { - *ofs = parentOfs( dir ); - *count = parentSize( dir ); - } else if (!Q_stricmp( token, "angles")) { - *ofs = parentOfs( angles ); - *count = parentSize( angles ); - } else if (!Q_stricmp( token, "shader")) { - *ofs = parentOfs( shader ); - *count = parentSize( shader ); - } else if (!Q_stricmp( token, "model")) { - *ofs = parentOfs( model ); - *count = parentSize( model ); - } else if (!Q_stricmp( token, "size")) { - *ofs = parentOfs( size ); - *count = parentSize( size ); - } else if (!Q_stricmp( token, "width")) { - *ofs = parentOfs( width ); - *count = parentSize( width ); - } else if (!Q_stricmp( token, "yaw")) { - *ofs = parentOfs( angles[YAW] ); - *count = parentSize( angles[YAW] ); - } else if (!Q_stricmp( token, "pitch")) { - *ofs = parentOfs( angles[PITCH] ); - *count = parentSize( angles[PITCH] ); - } else if (!Q_stricmp( token, "roll")) { - *ofs = parentOfs( angles[ROLL] ); - *count = parentSize( angles[ROLL] ); - } else if (!Q_stricmp( token, "angle")) { - *ofs = parentOfs( angles[ROLL] ); - *count = parentSize( angles[ROLL] ); - } else if (!Q_stricmp( token, "color")) { - *ofs = parentOfs( color ); - *count = parentSize( color ); - } else if (!Q_stricmp( token, "color2")) { - *ofs = parentOfs( color2 ); - *count = parentSize( color2 ); - } else { - return fxParseError( parse, "Unknown parent tag %s", token ); - } - return qtrue; -} - -static qboolean fxParseColorMathOut( fxParse_t *parse, fxParseOut_t *out, unsigned int index ) { - fxRunColorMath_t colorMath; - colorMath.index = index; - if (!fxParseOutCmd( parse, out, fxCmdColorMath, &colorMath, sizeof( colorMath ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - fxParseWrite( parse, FX_MASK_COLOR ); - return qtrue; -} - -static qboolean fxParseBlock( fxParse_t *parse, fxParseOut_t *out ); - -static qboolean fxParseIfBlock( fxParse_t *parse, fxParseOut_t *out ) { - int *blockSize = (int *)(out->data + out->used); - /* Store an int to contain the block size */ - if (!fxParseOut( parse, out, blockSize, sizeof( int ))) - return qfalse; - blockSize[0] = out->used; - if (!fxParseBlock( parse, out )) - return qfalse; - /* Store the blocksize in front of the block */ - blockSize[0] = out->used - blockSize[0]; - return qtrue; -} - -/* This is started up with a parsed token alread in the parse */ -static qboolean fxParseBlock( fxParse_t *parse, fxParseOut_t *out ) { - byte temp[1024]; - const char *token = parse->token; - - if (!fxParseToken( parse, qtrue )) { - return fxParseError( parse, "missing opening paranthesis" ); - } - if (Q_stricmp( token, "{" )) - return fxParseError( parse, "no opening paranthesis, got %s", token ); - - while ( 1 ) { - if (!fxParseToken( parse, qtrue )) { - return fxParseError( parse, "missing closing paranthesis" ); - } - if ( parse->emitter ) { - fxRunEmitter_t *emitter = parse->emitter; - if (!Q_stricmp( token, "moveGravity" ) ) { - if (!fxParseFloat( parse, &emitter->gravity )) - return qfalse; - emitter->flags |= FX_EMIT_MOVE; - continue; - } else if (!Q_stricmp( token, "moveBounce" ) ) { - if (!fxParseFloat( parse, &emitter->gravity )) - return qfalse; - if (!fxParseFloat( parse, &emitter->bounceFactor )) - return qfalse; - emitter->flags |= FX_EMIT_MOVE | FX_EMIT_TRACE; - continue; - } else if (!Q_stricmp( token, "impactDeath" ) ) { - if (!fxParseFloat( parse, &emitter->gravity )) - return qfalse; - emitter->flags |= FX_EMIT_MOVE | FX_EMIT_TRACE | FX_EMIT_IMPACT; - continue; - } else if (!Q_stricmp( token, "sink" ) ) { - if (!fxParseFloat( parse, &emitter->sinkDelay )) - return qfalse; - if (!fxParseFloat( parse, &emitter->sinkDepth )) - return qfalse; - //Scale the sinkdepth up for easy multiplying later - emitter->sinkDepth *= 1.0f / ( 1.0f - emitter->sinkDelay ); - emitter->flags |= FX_EMIT_MOVE | FX_EMIT_SINK; - continue; - } else if (!Q_stricmp( token, "impact" ) ) { - fxParseOut_t impactOut; - fxRunSkip_t *skip = (fxRunSkip_t *)temp; - - if (!fxParseFloat( parse, &emitter->impactSpeed )) - return qfalse; - - emitter->impactSpeed *= emitter->impactSpeed; - emitter->flags |= FX_EMIT_MOVE | FX_EMIT_TRACE; - - impactOut.data = temp; - impactOut.size = sizeof( temp ); - impactOut.used = sizeof( fxRunSkip_t ); - if (!fxParseBlock( parse, &impactOut )) - return qfalse; - skip->size = impactOut.used; - - emitter->impactRun = out->used + sizeof( void *) + sizeof( fxRunSkip_t ); - if (!fxParseOutCmd( parse, out, fxCmdSkip, skip, skip->size )) - return qfalse; - continue; - } else if (!Q_stricmp( token, "death" ) ) { - fxParseOut_t deathOut; - fxRunSkip_t *skip = (fxRunSkip_t *)temp; - - deathOut.data = temp; - deathOut.size = sizeof( temp ); - deathOut.used = sizeof( fxRunSkip_t ); - if (!fxParseBlock( parse, &deathOut )) - return qfalse; - skip->size = deathOut.used; - - emitter->deathRun = out->used + sizeof( void *) + sizeof( fxRunSkip_t ); - if (!fxParseOutCmd( parse, out, fxCmdSkip, skip, skip->size )) - return qfalse; - continue; - } - } - if (0) { - } else if (!Q_stricmp( token, "shaderClear" ) ) { - fxRunShader_t shader; - shader.shader = 0; - if (!fxParseOutCmd( parse, out, fxCmdShader, &shader, sizeof( shader ))) - return qfalse; - fxParseWrite( parse, FX_MASK_SHADER ); - } else if (!Q_stricmp( token, "shader" ) ) { - fxRunShader_t shader; - if (!fxParseWord( parse, "shadername" )) - return qfalse; - if (!fxMatchShader( parse, &shader.shader )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdShader, &shader, sizeof( shader ))) - return qfalse; - fxParseWrite( parse, FX_MASK_SHADER ); - } else if (!Q_stricmp( token, "model" ) ) { - fxRunModel_t model; - if (!fxParseWord( parse, "modelname" )) - return qfalse; - if (!fxMatchModel( parse, &model.model )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdModel, &model, sizeof( model ))) - return qfalse; - fxParseWrite( parse, FX_MASK_MODEL ); - } else if (!Q_stricmp( token, "sound" ) ) { - fxRunSound_t sound; - if (!fxParseWord( parse, "soundname" )) - return qfalse; - if (!fxMatchSound( parse, &sound.handle )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSound, &sound, sizeof( sound ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN ); - } else if (!Q_stricmp( token, "shaderList" ) ) { - fxRunShaderList_t *shaderList = (fxRunShaderList_t *)&temp; - fxParseOut_t shaderListOut; - - shaderListOut.data = temp; - shaderListOut.size = sizeof( temp ); - shaderListOut.used = sizeof( fxRunShaderList_t ); - if (!fxParseMath( parse, &shaderListOut )) - return qfalse; - if (!fxParseList( parse, "shaderList", fxMatchShader, sizeof (qhandle_t ), - temp + shaderListOut.used, - ( shaderListOut.size - shaderListOut.used ) / sizeof (qhandle_t ), - &shaderList->count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdShaderList, temp, shaderListOut.used + shaderList->count * sizeof( qhandle_t ) )) - return qfalse; - fxParseWrite( parse, FX_MASK_SHADER ); - } else if (!Q_stricmp( token, "modelList" ) ) { - fxRunModelList_t *modelList = (fxRunModelList_t *)&temp; - fxParseOut_t modelListOut; - - modelListOut.data = temp; - modelListOut.size = sizeof( temp ); - modelListOut.used = sizeof( fxRunModelList_t ); - if (!fxParseMath( parse, &modelListOut )) - return qfalse; - if (!fxParseList( parse, "modelList", fxMatchModel, sizeof (qhandle_t ), - temp + modelListOut.used, - ( modelListOut.size - modelListOut.used ) / sizeof (qhandle_t ), - &modelList->count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdModelList, temp, modelListOut.used + modelList->count * sizeof( qhandle_t ) )) - return qfalse; - fxParseWrite( parse, FX_MASK_MODEL ); - } else if (!Q_stricmp( token, "colorList" ) ) { - fxRunColorList_t *colorList = (fxRunColorList_t *)&temp; - fxParseOut_t colorListOut; - - colorListOut.data = temp; - colorListOut.size = sizeof( temp ); - colorListOut.used = sizeof( fxRunColorList_t ); - if (!fxParseMath( parse, &colorListOut )) - return qfalse; - if (!fxParseList( parse, "colorList", fxMatchColor, sizeof( color4ub_t ), - temp + colorListOut.used, - ( colorListOut.size - colorListOut.used ) / sizeof( color4ub_t ), - &colorList->count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdColorList, temp, colorListOut.used + colorList->count * sizeof( color4ub_t ) )) - return qfalse; - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "colorBlend" ) ) { - fxRunColorBlend_t *colorBlend = (fxRunColorBlend_t *)&temp; - fxParseOut_t colorBlendOut; - - colorBlendOut.data = temp; - colorBlendOut.size = sizeof( temp ); - colorBlendOut.used = sizeof( fxRunColorBlend_t ); - if (!fxParseMath( parse, &colorBlendOut )) - return qfalse; - if (!fxParseList( parse, "colorBlend", fxMatchColor, sizeof( color4ub_t ), - temp + colorBlendOut.used, - ( colorBlendOut.size - colorBlendOut.used ) / sizeof( color4ub_t ), - &colorBlend->count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdColorBlend, temp, colorBlendOut.used + colorBlend->count * sizeof( color4ub_t ) )) - return qfalse; - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "soundList" ) ) { - fxRunSoundList_t *soundList = (fxRunSoundList_t *)&temp; - if (!fxParseList( parse, "SoundList", fxMatchSound, sizeof( sfxHandle_t ), - soundList + 1, - (sizeof(temp) - sizeof( *soundList)) / sizeof( sfxHandle_t ), - &soundList->count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSoundList, temp, sizeof(soundList) + soundList->count * sizeof( sfxHandle_t ) )) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN ); - } else if (!Q_stricmp( token, "loopSound" ) ) { - fxRunLoopSound_t loopSound; - if (!fxParseWord( parse, "Soundname" )) { - return qfalse; - } - loopSound.handle = S_RegisterSound( token, qfalse ); - if (!fxParseOutCmd( parse, out, fxCmdLoopSound, &loopSound, sizeof( loopSound ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_VELOCITY ); - } else if (!Q_stricmp( token, "Sprite" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSprite, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_ROTATE | FX_MASK_SHADER | FX_MASK_SIZE ); - } else if (!Q_stricmp( token, "Spark" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSpark, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_VELOCITY | FX_MASK_COLOR | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_WIDTH ); - } else if (!Q_stricmp( token, "Quad" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdQuad, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_ROTATE | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_DIR ); - } else if (!Q_stricmp( token, "Beam" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdBeam, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_ROTATE | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_DIR ); - } else if (!Q_stricmp( token, "Rings" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdRings, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_ROTATE | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_WIDTH | FX_MASK_DIR ); - } else if (!Q_stricmp( token, "anglesModel" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdAnglesModel, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_ANGLES | FX_MASK_MODEL ); - } else if (!Q_stricmp( token, "axisModel" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdAxisModel, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_AXIS | FX_MASK_MODEL ); - } else if (!Q_stricmp( token, "dirModel" ) ) { - fxRunRender_t runRender; - if (!fxParseRenderFX( parse, &runRender.renderfx )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdDirModel, &runRender, sizeof( runRender ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_SHADER | FX_MASK_SIZE | FX_MASK_DIR | FX_MASK_MODEL | FX_MASK_ROTATE ); - } else if (!Q_stricmp( token, "Light" ) ) { - if (!fxParseOutCmd( parse, out, fxCmdLight, 0, 0 )) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_SIZE ); - } else if (!Q_stricmp( token, "Decal" ) ) { - fxRunDecal_t decal; - decal.flags = 0; - decal.life = 10000; - - while (fxParseToken( parse, qfalse ) ) { - if (!Q_stricmp(token, "temp")) { - decal.flags |= DECAL_TEMP; - } else if (!Q_stricmp(token, "alpha")) { - decal.flags |= DECAL_ALPHA; - } else if (!Q_stricmp(token, "energy")) { - decal.flags |= DECAL_ENERGY; - //Last one has to be a float life - } else { - if (!fxMatchValidFloat( parse )) - return qfalse; - decal.life = atof( token ) * 1000; - } - } - if ( decal.life <= 0 ) { - decal.life = 10000; - } - if (!fxParseOutCmd( parse, out, fxCmdDecal, &decal, sizeof( decal ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_COLOR | FX_MASK_SIZE | FX_MASK_DIR ); - } else if (!Q_stricmp( token, "Trace" ) ) { - if (!fxParseOutCmd( parse, out, fxCmdTrace, 0, 0)) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN | FX_MASK_DIR ); - fxParseWrite( parse, FX_MASK_ORIGIN | FX_MASK_DIR ); - } else if (!Q_stricmp( token, "vibrate" ) ) { - fxRunVibrate_t vibrate; - if (!fxParseFloat( parse, &vibrate.strength )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdVibrate, &vibrate, sizeof( vibrate ))) - return qfalse; - fxParseRead( parse, FX_MASK_ORIGIN ); - } else if (!Q_stricmp( token, "alphaFade" ) ) { - fxRunAlphaFade_t alphaFade; - if (!fxParseFloat( parse, &alphaFade.delay )) - return qfalse; - if ( alphaFade.delay < 0 || alphaFade.delay >= 1.0f ) - return fxParseError( parse, "Fade value %f illegal", alphaFade.delay ); - alphaFade.scale = -255.0f / (1.0f - alphaFade.delay ); - if (!fxParseOutCmd( parse, out, fxCmdAlphaFade, &alphaFade, sizeof( alphaFade ))) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR ); - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "color" ) ) { - fxRunColor_t color; - if (!fxParseColor( parse, color.value )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdColor, &color, sizeof( color ))) - return qfalse; - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "colorFade" ) ) { - fxRunColorFade_t colorFade; - if (!fxParseFloat( parse, &colorFade.delay )) - return qfalse; - if ( colorFade.delay < 0 || colorFade.delay >= 1.0f ) - return fxParseError( parse, "Fade value %f illegal", colorFade.delay ); - colorFade.scale = -255.0f / (1.0f - colorFade.delay ); - if (!fxParseOutCmd( parse, out, fxCmdColorFade, &colorFade, sizeof( colorFade ))) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR ); - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "colorScale" ) ) { - if (!fxParseOutCmd( parse, out, fxCmdColorScale, 0, 0 )) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - fxParseRead( parse, FX_MASK_COLOR ); - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "colorHue" ) ) { - if (!fxParseOutCmd( parse, out, fxCmdColorHue, 0, 0)) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - fxParseWrite( parse, FX_MASK_COLOR ); - } else if (!Q_stricmp( token, "red" ) ) { - if (!fxParseColorMathOut( parse, out, 0 )) - return qfalse; - } else if (!Q_stricmp( token, "green" ) ) { - if (!fxParseColorMathOut( parse, out, 1 )) - return qfalse; - } else if (!Q_stricmp( token, "blue" ) ) { - if (!fxParseColorMathOut( parse, out, 2 )) - return qfalse; - } else if (!Q_stricmp( token, "alpha" ) ) { - if (!fxParseColorMathOut( parse, out, 3 )) - return qfalse; - } else if (!Q_stricmp( token, "wobble" ) ) { - fxRunWobble_t wobble; - - if (!fxParseVectorRead( parse, &wobble.src )) - return qfalse; - if (!fxParseVectorWrite( parse, &wobble.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdWobble, &wobble, sizeof( wobble ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - } else if (!Q_stricmp( token, "makeAngles" ) ) { - fxRunMakeAngles_t makeAngles; - - if (!fxParseVectorRead( parse, &makeAngles.src )) - return qfalse; - makeAngles.dst = makeAngles.src; - if (!fxParseVectorOptional( parse, &makeAngles.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdMakeAngles, &makeAngles, sizeof( makeAngles ))) - return qfalse; - } else if (!Q_stricmp( token, "inverse" ) ) { - fxRunInverse_t inverse; - - if (!fxParseVectorRead( parse, &inverse.src )) - return qfalse; - inverse.dst = inverse.src; - fxParseVectorOptional( parse, &inverse.dst ); - if (!fxParseOutCmd( parse, out, fxCmdInverse, &inverse, sizeof( inverse ))) - return qfalse; - } else if (!Q_stricmp( token, "normalize" ) ) { - fxRunNormalize_t normalize; - - if (!fxParseVectorRead( parse, &normalize.src )) - return qfalse; - normalize.dst = normalize.src; - fxParseVectorOptional( parse, &normalize.dst ); - if (!fxParseOutCmd( parse, out, fxCmdNormalize, &normalize, sizeof( normalize ))) - return qfalse; - } else if (!Q_stricmp( token, "perpendicular" ) ) { - fxRunPerpendicular_t perpendicular; - - if (!fxParseVectorRead( parse, &perpendicular.src )) - return qfalse; - perpendicular.dst = perpendicular.src; - fxParseVectorOptional( parse, &perpendicular.dst ); - if (!fxParseOutCmd( parse, out, fxCmdPerpendicular, &perpendicular, sizeof( perpendicular ))) - return qfalse; - } else if (!Q_stricmp( token, "clear" ) ) { - fxRunClear_t clear; - if (!fxParseVectorWrite( parse, &clear.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdClear, &clear, sizeof( clear ))) - return qfalse; - } else if (!Q_stricmp( token, "copy" ) ) { - fxRunCopy_t copy; - if (!fxParseVectorRead( parse, ©.src )) - return qfalse; - if (!fxParseVectorWrite( parse, ©.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdCopy, ©, sizeof( copy ))) - return qfalse; - } else if (!Q_stricmp( token, "scale" ) ) { - fxRunScale_t scale; - - if (!fxParseVectorRead( parse, &scale.src )) - return qfalse; -// scale.dst = scale.src; - if (!fxParseVectorWrite( parse, &scale.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdScale, &scale, sizeof( scale ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - } else if (!Q_stricmp( token, "add" ) ) { - fxRunAdd_t add; - - if (!fxParseVectorRead( parse, &add.src1 )) - return qfalse; - if (!fxParseVectorRead( parse, &add.src2 )) - return qfalse; - if (!fxParseVectorWrite( parse, &add.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdAdd, &add, sizeof( add ))) - return qfalse; - } else if (!Q_stricmp( token, "sub" ) ) { - fxRunSub_t sub; - - if (!fxParseVectorRead( parse, &sub.src1 )) - return qfalse; - if (!fxParseVectorRead( parse, &sub.src2 )) - return qfalse; - if (!fxParseVectorWrite( parse, &sub.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSub, &sub, sizeof( sub ))) - return qfalse; - } else if (!Q_stricmp( token, "addScale" ) ) { - fxRunAddScale_t addScale; - - if (!fxParseVectorRead( parse, &addScale.src )) - return qfalse; - if (!fxParseVectorRead( parse, &addScale.scale )) - return qfalse; - if (!fxParseVectorWrite( parse, &addScale.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdAddScale, &addScale, sizeof( addScale ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - } else if (!Q_stricmp( token, "subScale" ) ) { - fxRunSubScale_t subScale; - - if (!fxParseVectorRead( parse, &subScale.src )) - return qfalse; - if (!fxParseVectorRead( parse, &subScale.scale )) - return qfalse; - if (!fxParseVectorWrite( parse, &subScale.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdSubScale, &subScale, sizeof( subScale ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - } else if (!Q_stricmp( token, "rotateAround" ) ) { - fxRunRotateAround_t rotateAround; - - if (!fxParseVectorRead( parse, &rotateAround.src )) - return qfalse; - if (!fxParseVectorRead( parse, &rotateAround.dir )) - return qfalse; - if (!fxParseVectorWrite( parse, &rotateAround.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdRotateAround, &rotateAround, sizeof( rotateAround ))) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - } else if (!Q_stricmp( token, "random" ) ) { - fxRunRandom_t random; - if (!fxParseVectorWrite( parse, &random.dst )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdRandom, &random, sizeof( random ))) - return qfalse; - } else if (!Q_stricmp( token, "kill" ) ) { - if (!fxParseOutCmd( parse, out, fxCmdKill, 0, 0 )) - return qfalse; - } else if (!Q_stricmp( token, "emitter" ) || !Q_stricmp( token, "entity" )) { - fxRunEmitter_t *oldEmitter; - fxRunEmitter_t *newEmitter = (fxRunEmitter_t *)temp; - fxParseOut_t emitterOut; - unsigned oldReadMask, oldWriteMask, newReadMask; - int oldLoopDepth; - - memset( newEmitter, 0, sizeof( fxRunEmitter_t ) ); - - emitterOut.data = temp; - emitterOut.size = sizeof( temp ); - emitterOut.used = sizeof( fxRunEmitter_t ); - if (!fxParseMath( parse, &emitterOut )) - return qfalse; - newEmitter->emitRun = emitterOut.used; - oldEmitter = parse->emitter; - oldReadMask = parse->readMask; - oldWriteMask = parse->writeMask; - oldLoopDepth = parse->loopDepth; - - parse->emitter = newEmitter; - parse->loopDepth = 0; - parse->readMask = 0; - parse->writeMask = 0; - if (!fxParseBlock( parse, &emitterOut )) - return qfalse; - //Create copy table and extra size requirements - if (!fxParseCreateMask( parse, newEmitter->mask, sizeof( newEmitter->mask ), &newEmitter->allocSize )) - return qfalse; - newEmitter->allocSize += sizeof( fxEntity_t ); - newEmitter->size = emitterOut.used; - //Emitters only read, restore the rest of the previous version - newReadMask = parse->readMask; - parse->readMask = oldReadMask; - parse->writeMask = oldWriteMask; - parse->loopDepth = oldLoopDepth; - //forward readmask to caller - fxParseRead( parse, newReadMask ); - parse->emitter = oldEmitter; - if (!fxParseOutCmd( parse, out, fxCmdEmitter, newEmitter, emitterOut.used )) - return qfalse; - - } else if (!Q_stricmp( token, "interval" ) ) { - fxRunInterval_t *Interval = (fxRunInterval_t *)temp; - fxParseOut_t intervalOut; - - parse->loopDepth++; - intervalOut.data = temp; - intervalOut.size = sizeof( temp ); - intervalOut.used = sizeof( fxRunInterval_t ); - if (!fxParseMath( parse, &intervalOut )) - return qfalse; - if (!fxParseBlock( parse, &intervalOut )) - return qfalse; - Interval->size = intervalOut.used; - if (!fxParseOutCmd( parse, out, fxCmdInterval, Interval, intervalOut.used )) - return qfalse; - parse->loopDepth--; - - } else if (!Q_stricmp( token, "repeat" ) ) { - fxRunRepeat_t *repeat = (fxRunRepeat_t *)temp; - fxParseOut_t repeatOut; - - repeatOut.data = temp; - repeatOut.size = sizeof( temp ); - repeatOut.used = sizeof( fxRunRepeat_t ); - parse->loopDepth++; - if (!fxParseMath( parse, &repeatOut )) - return qfalse; - if (!fxParseBlock( parse, &repeatOut )) - return qfalse; - repeat->size = repeatOut.used; - if (!fxParseOutCmd( parse, out, fxCmdRepeat, repeat, repeatOut.used )) - return qfalse; - parse->loopDepth--; - } else if (!Q_stricmp( token, "distance" ) ) { - fxRunDistance_t *distance = (fxRunDistance_t *)temp; - fxParseOut_t distanceOut; - - parse->loopDepth++; - distanceOut.data = temp; - distanceOut.size = sizeof( temp ); - distanceOut.used = sizeof( fxRunDistance_t ); - if (!fxParseMath( parse, &distanceOut )) - return qfalse; - if (!fxParseBlock( parse, &distanceOut )) - return qfalse; - distance->size = distanceOut.used; - if (!fxParseOutCmd( parse, out, fxCmdDistance, distance, distanceOut.used )) - return qfalse; - parse->loopDepth--; - fxParseRead( parse, FX_MASK_ORIGIN ); - } else if (!Q_stricmp( token, "if" ) ) { - fxRunIf_t *doIf = (fxRunIf_t *)temp; - fxParseOut_t ifOut; - - doIf->testCount = 1; - doIf->elseStep = 0; - ifOut.data = temp; - ifOut.size = sizeof( temp ); - ifOut.used = sizeof( fxRunIf_t ); - if (!fxParseMath( parse, &ifOut )) - return qfalse; - if (!fxParseIfBlock( parse, &ifOut )) - return qfalse; - while (1) { - if (!fxParseToken( parse, qfalse )) - break; - if (!Q_stricmp( token, "elif")) { - doIf->testCount += 1; - if (!fxParseMath( parse, &ifOut )) - return qfalse; - if (!fxParseIfBlock( parse, &ifOut )) - return qfalse; - } else if (!Q_stricmp( token, "else" )) { - doIf->elseStep = qtrue; - if (!fxParseBlock( parse, &ifOut )) - return qfalse; - break; - } - } - /* Calculate the total size for the final exit */ - doIf->size = ifOut.used; - if (!fxParseOutCmd( parse, out, fxCmdIf, doIf, ifOut.used )) - return qfalse; - } else if (!Q_stricmp( token, "once" ) ) { - fxRunOnce_t *once = (fxRunOnce_t *)temp; - fxParseOut_t onceOut; - - onceOut.data = temp; - onceOut.size = sizeof( temp ); - onceOut.used = sizeof( fxRunOnce_t ); - if (!fxParseBlock( parse, &onceOut )) - return qfalse; - once->size = onceOut.used; - if (!fxParseOutCmd( parse, out, fxCmdOnce, once, onceOut.used )) - return qfalse; - } else if (!Q_stricmp( token, "pushParent" ) ) { - fxRunPushParent_t push; - if (!fxParseParentName( parse, &push.offset, &push.count )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdPushParent, &push, sizeof( push ))) - return qfalse; - fxParseRead( parse, FX_MASK_PARENT ); - } else if (!Q_stricmp( token, "push" ) ) { - int mask; - fxRunPush_t push; - if (!fxParseStackName( parse, &push.offset, &push.count, &mask )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdPush, &push, sizeof( push ))) - return qfalse; - fxParseRead( parse, mask ); - } else if (!Q_stricmp( token, "pop" ) ) { - int mask; - fxRunPop_t pop; - - if (!fxParseStackName( parse, &pop.offset, &pop.count, &mask )) - return qfalse; - if (!fxParseOutCmd( parse, out, fxCmdPop, &pop, sizeof( pop ))) - return qfalse; - fxParseWrite( parse, mask ); - } else if (!Q_stricmp( token, "script" ) ) { - fxRunScript_t script; - fxScript_t *loadScript; - - if (!fxParseWord( parse, "scriptname" )) - return qfalse; - loadScript = fxFindScript( token ); - if (!loadScript ) - return fxParseError( parse, "Can't load script %s", token ); - script.data = loadScript->data; - fxParseRead( parse, loadScript->readMask ); - if (!fxParseOutCmd( parse, out, fxCmdScript, &script, sizeof( script ))) - return qfalse; - } else if (!Q_stricmp( token, "}" ) ) { - if (!fxParseOutCmd( parse, out, 0, 0, 0 )) - return qfalse; - return qtrue; - } else { - unsigned int mask; - fxRunValue_t value; - if (fxMatchFloat( token, &value.dst, &mask)) { - if (!fxParseOutCmd( parse, out, fxCmdValue, &value, sizeof( value ) )) - return qfalse; - if (!fxParseMath( parse, out )) - return qfalse; - fxParseWrite( parse, mask ); - } else { - return fxParseError( parse, "Unknown token %s", parse->token ); - } - } - } - return qfalse; -} - -static fxScript_t *fxParseScript( fxHashEntry_t *entry ) { - fxParse_t parse; - fxParseOut_t parseOut; - fxScript_t *script; - char parseData[ 32*1024]; - byte *allocBuf; - int allocSize; - - /* Check if this one has already been loaded */ - if ( entry->script ) - return entry->script; - - if ( fx.scriptCount >= FX_MAX_SCRIPTS ) { - Com_Printf( "fx script limit reached" ); - return 0; - } - - /* Prepare variables for parsing the text */ - memset( &parse, 0, sizeof( parse )); - parse.text = entry->text; - parse.name = entry->name; - - parseOut.data = parseData; - parseOut.used = 0; - parseOut.size = sizeof( parseData ); - - if (!fxParseBlock( &parse, &parseOut )) - return 0; - - /* Allocate the script struct and set it up */ - allocSize = parseOut.used + sizeof( fxScript_t ); - allocBuf = fxParseAlloc( allocSize ); - script = (fxScript_t *) allocBuf; - script->remap = 0; - script->readMask = parse.readMask; - Com_Memcpy( &script->data, parseOut.data, parseOut.used ); - entry->script = script; - script->entry = entry; - /* Register script in table an increase scriptcount */ - fx.scripts[ fx.scriptCount ] = script; - script->handle = fx.scriptCount; - fx.scriptCount++; - return script; -} - - -#define SCAN_ENTRIES 256 -typedef struct fxScanBlock_s { - fxHashEntry_t entries[SCAN_ENTRIES]; - int entriesUsed; - struct fxScanBlock_s *next; -} fxScanBlock_t; - -static char *scanSkipSpaces( char *p ) { - for (;*p;p++) - if ((*p != ' ') && (*p != '\t') && (*p != '\n')) - break; - return p; -} -/* This will modify the original string */ -static char *scanMakeWord( char **input ) { - char *ret; - char *p = *input; - - p = scanSkipSpaces( p ); - ret = p; - for (;*p;p++) { - if (*p == ' ' || *p == '\t' || *p == '\n') { - *p++ = 0; - break; - } - } - *input = p; - return ret; -} - -static char *scanMakeSection( char **input ) { - char *ret; - char *p = *input; - int braceDepth = 1; - - p = scanSkipSpaces( p ); - if ( p[0] != '{') - return 0; - ret = p; - p++; - for (;*p;p++) { - if ( p[0] == '{') { - braceDepth++; - } else if ( p[0] == '}') { - braceDepth--; - if (!braceDepth) { - if (p[1]) { - p[1] = 0; - p+=2; - } else { - p += 1; - } - break; - } - } - } - if ( braceDepth ) - return 0; - *input = p; - return ret; -} - -static int scanCopyString( char *dst, const char *src, int left ) { - int done = 0; - if ( left <= 0) - return 0; - while (left > 1 && src[done]) { - dst[done] = src[done]; - done++; - left--; - } - dst[done] = 0; - done++; - return done; -} - -static void fxScanDir( const char *dirName, void **buffers, int *numFiles) { - int i, dirFiles; - char **fxFiles; - - fxFiles = FS_ListFiles( "scripts", ".fx", &dirFiles ); - - // load the files first time - for ( i = 0; i < dirFiles; i++ ) { - char filename[MAX_QPATH]; - if (*numFiles >= FX_MAX_SCRIPTS) { - Com_Error( ERR_DROP, "Too many .fx files" ); - } - Com_sprintf( filename, sizeof( filename ), "%s/%s", dirName, fxFiles[i] ); - FS_ReadFile( filename, &buffers[numFiles[0]] ); - numFiles[0]++; - } - FS_FreeFileList( fxFiles ); -} - -static void *emptyScript[2]; -static void fxScanFiles( void ) { - char *buffers[FX_MAX_SCRIPTS]; - int numFiles; - int allocSize; - int i; - fxHashEntry_t *entryWrite; - int entrySize, nameSize, textSize; - char *allocBuf, *nameWrite, *textWrite; - fxScanBlock_t *scanBlock = 0; - fxHashEntry_t *tempHash[FX_HASH_SIZE]; - - /* Clear some stuff just to be safe */ - fx.alloc.entries = 0; - memset( fx.scripts, 0, sizeof( fx.scripts )); - memset( fx.entryHash, 0, sizeof( fx.entryHash )); - /* Init the default handle for an invalid/empty script*/ - fx.scripts[0] = (fxScript_t *)emptyScript; - fx.scriptCount = 1; - // scan for FX files - Com_Memset( tempHash, 0, sizeof( tempHash )); - numFiles = 0; - fxScanDir( "scripts", buffers, &numFiles ); - if ( fx_Override->string[0] ) { - int i; - Cmd_TokenizeString( fx_Override->string ); - for( i=0; inext ) { - if ( Q_stricmp( entry->name, name )) - continue; - /* Override the current entry */ - entry->name = name; - entry->text = section; - break; - } - /* Didn't find an entry, add a new one */ - if (!entry) { - /* Get an entry from the block */ - if ( !scanBlock || scanBlock->entriesUsed == SCAN_ENTRIES) { - fxScanBlock_t *newBlock = Hunk_AllocateTempMemory( sizeof( fxScanBlock_t )); - newBlock->entriesUsed = 0; - newBlock->next = scanBlock; - scanBlock = newBlock; - } - entry = &scanBlock->entries[scanBlock->entriesUsed++]; - entry->name = name; - entry->text = section; - entry->next = tempHash[hashIndex]; - tempHash[hashIndex] = entry; - } - } - } - /* Scan through our hash and determine allocation sizes */ - nameSize = 0; textSize = 0; entrySize = 0; - allocSize = 0; - for ( i = 0; i < FX_HASH_SIZE; i++) { - fxHashEntry_t *entry; - for (entry = tempHash[i]; entry; entry = entry->next ) { - entrySize += sizeof( fxHashEntry_t ); - nameSize += strlen( entry->name ) + 1; - textSize += strlen( entry->text ) + 1; - } - } - /* List of entries in front, then all the names, then all the text */ - allocBuf = (char*) fxParseAlloc( entrySize + nameSize + textSize ); - fx.alloc.entries = (fxHashEntry_t*)allocBuf; - entryWrite = fx.alloc.entries; - nameWrite = allocBuf + entrySize; - textWrite = allocBuf + entrySize + nameSize; - /* Silly overkill to ensure that names are read linearly, oh well */ - for ( i = 0; i < FX_HASH_SIZE; i++) { - fxHashEntry_t *entry, *newEntry, *startEntry; - newEntry = 0; - startEntry = entryWrite; - for (entry = tempHash[i]; entry; entry = entry->next ) { - int len; - newEntry = entryWrite++; - - memset( newEntry, 0, sizeof (*newEntry)); - newEntry->next = entryWrite; - - newEntry->name = nameWrite; - len = scanCopyString( nameWrite, entry->name, nameSize ); - nameSize -= len; nameWrite += len; - - newEntry->text = textWrite; - len = scanCopyString( textWrite, entry->text, textSize ); - textSize -= len; textWrite += len; - } - if ( newEntry ) { - fx.entryHash[i] = startEntry; - newEntry->next = 0; - } - } - /* Free all allocated memory in the good order hopefully */ - while (scanBlock) { - fxScanBlock_t *next = scanBlock->next; - Hunk_FreeTempMemory( scanBlock ); - scanBlock = next; - } - for ( i = numFiles-1; i >=0; i-- ) - FS_FreeFile( buffers[i] ); -} - -static fxScript_t *fxFindScript( const char *name ) { - unsigned int hashIndex; - fxHashEntry_t *entry; - if (!name) - return 0; - - hashIndex = fxGenerateHash( name ); - for ( entry = fx.entryHash[ hashIndex ]; entry; entry = entry->next ) { - if (!Q_stricmp( entry->name, name )) { - return fxParseScript( entry ); - } - } - return 0; -} - -fxHandle_t FX_Register( const char *name ) { - const fxScript_t *script; - script = fxFindScript( name ); - if ( fx_Debug->integer ) { - Com_Printf( "FX_Debug:Registering script %s, %s\n", name, script ? "success" : "failed" ); - } - if ( script ) - return script->handle; - return 0; -} - -static void fxRemap( void ) { - const char *map1, *map2; - fxScript_t *script1, *script2; - - if ( Cmd_Argc() < 1 ) { - Com_Printf("fxRemap oldScript newScript, will replace oldscript with new one\n" ); - Com_Printf("fxRemap oldScript, will reset the remap\n" ); - return; - } - map1 = Cmd_Argv( 1 ); - script1 = fxFindScript( map1 ); - if (!script1) { - Com_Printf( "fxScript %s not found\n", map1 ); - return; - } - if ( Cmd_Argc() > 2) { - map2 = Cmd_Argv( 2 ); - script2 = fxFindScript( map2 ); - if (!script2) { - Com_Printf( "fxScript %s not found\n", map2 ); - return; - } - script1->remap = script2; - Com_Printf("Remapped %s to %s", script1->entry->name, script2->entry->name ); - } else { - Com_Printf("Cleared remapping on script %s", script1->entry->name ); - script1->remap = 0; - } -} - -static void fxReload( void ) { - fxScript_t *scripts[FX_MAX_SCRIPTS]; - fxHashEntry_t *entries = fx.alloc.entries; - fxHashEntry_t *entryHash[FX_HASH_SIZE]; - int scriptCount; - int i; - - FX_Reset(); - - scriptCount = fx.scriptCount; - for ( i = 1; i < scriptCount;i++ ) { - scripts[i] = fx.scripts[i]; - fx.scripts[i] = 0; - } - for ( i = 0; i < FX_HASH_SIZE;i++ ) { - entryHash[i] = fx.entryHash[i]; - fx.entryHash[i] = 0; - } - fx.alloc.entries = 0; - /* Rescan all the files */ - fxScanFiles(); - /* Reload all the scripts in the same order */ - for (i = 1; i < scriptCount;i++ ) { - int c; - const char *name = scripts[i]->entry->name; - fxScript_t *load = fxFindScript( name ); - if ( load && load->handle == i ) - continue; - if (!load) - Com_Printf( "Failed to reload scripts %s\n", name ); - else - Com_Printf( "Script %s doesn't reload in the right handle\n", name ); - - /* Restore the old stuff and free the new stuff */ - for ( c = 1; c < fx.scriptCount; c++ ) - fxParseFree( fx.scripts[c] ); - fxParseFree( fx.alloc.entries ); - fx.scriptCount = scriptCount; - for ( c = 1; c < scriptCount; c++ ) - fx.scripts[c] = scripts[c]; - for ( c = 0; c< FX_HASH_SIZE; c++ ) - fx.entryHash[c] = entryHash[c]; - fx.alloc.entries = entries; - return; - } - /* Free the old stuff */ - for ( i = 1; i < scriptCount; i++ ) - fxParseFree( scripts[i] ); - fxParseFree( entries ); -} - - -static void fxMathTest( void ) { - char line[1024]; - char *lineP = line; - fxMathOut_t mathOut; - fxParse_t parse; - fxRun_t run; - - memset( &parse, 0, sizeof( parse )); - memset( &mathOut, 0, sizeof( mathOut )); - memset( &run, 0, sizeof( run )); - - Q_strncpyz( line, Cmd_ArgsFrom( 1 ), sizeof( line ) ); - if ( fxMathParse( &parse, mathParseLine, &lineP, 0, &mathOut ) ) { - fxMathInfo_t info; - info.data = (int *)mathOut.data; - info.run = &run; - Com_Printf( "result %f\n", fxMath( &info) ); - } -} - -void fxFreeMemory( void ) { - int i; - for ( i = 1; i < fx.scriptCount; i++ ) { - fxParseFree( fx.scripts[i] ); - fx.scripts[i] = 0; - } - fx.scriptCount = 0; - if ( fx.alloc.entries ) - fxParseFree( fx.alloc.entries ); - fx.alloc.entries = 0; -} - -void fxInitParser( void ) { - fxScanFiles(); - Cmd_AddCommand( "fxReload", fxReload ); - Cmd_AddCommand( "fxRemap", fxRemap ); - Cmd_AddCommand( "fxMath", fxMathTest ); -} - diff --git a/code/client/fx_public.h b/code/client/fx_public.h deleted file mode 100644 index 01bdce17..00000000 --- a/code/client/fx_public.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Sjoerd van der Berg ( harekiet @ gmail.com ) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// fx_public.h -- public fx definitions - -#include "fx_types.h" - -void FX_Init( void ); -void FX_Shutdown( void ); -fxHandle_t FX_Register( const char *name ); - -void FX_Debug( void ); -void FX_Reset( void ); -void FX_Begin( int time, float fraction ); -void FX_End( void ); -void FX_Run( fxHandle_t handle, const fxParent_t *parent, unsigned int key ); -void FX_VibrateView( float scale, vec3_t origin, vec3_t angles ); diff --git a/code/client/fx_types.h b/code/client/fx_types.h deleted file mode 100644 index 92547cd7..00000000 --- a/code/client/fx_types.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -=========================================================================== -Copyright (C) 2006 Sjoerd van der Berg ( harekiet @ gmail.com ) - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -// fx_types.h -- shared fx types -typedef int fxHandle_t; - -#define FXP_ORIGIN 0x0001 -#define FXP_VELOCITY 0x0002 -#define FXP_DIR 0x0004 -#define FXP_ANGLES 0x0008 -#define FXP_SIZE 0x0010 -#define FXP_WIDTH 0x0020 -#define FXP_COLOR 0x0040 -#define FXP_SHADER 0x0080 -#define FXP_MODEL 0x0100 -#define FXP_AXIS 0x0200 -#define FXP_LIFE 0x0400 - -typedef struct { - int flags; - vec3_t origin; - vec3_t velocity; - vec3_t dir; - color4ub_t color; - qhandle_t shader; - float life; - float size; - float width; - qhandle_t model; - vec3_t angles; - vec3_t axis[3]; - color4ub_t color2; -} fxParent_t; diff --git a/code/client/snd_codec_xmp.c b/code/client/snd_codec_xmp.c index 89db2292..b42129aa 100644 --- a/code/client/snd_codec_xmp.c +++ b/code/client/snd_codec_xmp.c @@ -43,7 +43,10 @@ void sound_deinit(void); - +static float fadey; +extern cvar_t *s_xmp_startPattern; +static int startpat; +static int gopat; extern int samplingrate; // from snd_dma void S_XMP_StartSong ( void ) @@ -58,6 +61,29 @@ void S_XMP_EndSong ( void ) +} + + +// TODO: A callback to set this appropriately from game context (monster sight, level triggers) +void S_XMP_CheckForFade ( void ) +{ + gopat = s_xmp_startPattern->integer; + + if ((gopat != startpat)) + { + fadey -= 0.025f; + // Com_Printf("AHHHFADING TO PATTERN %i!!! %f\n", startpat, fadey); + xmp_set_player(xmpsong, XMP_PLAYER_VOLUME, (fadey * 128)); + } + + if ((startpat != gopat) && (fadey < 0.01)) + { + startpat = gopat; + xmp_set_position(xmpsong, startpat); + xmp_set_player(xmpsong, XMP_PLAYER_VOLUME, 128); + fadey = 1; + } + } int aintistreaming = 0; @@ -79,7 +105,7 @@ S_XMP_CodecOpenStream ================= */ -// FIXME: there's a memory leak here if you start the same song many many many many times. +// FIXME: there's a memory leak here if you start the same song many many many many times? snd_stream_t *S_XMP_CodecOpenStream(const char *filename) { // First let's close whatever song we had.... @@ -123,14 +149,21 @@ snd_stream_t *S_XMP_CodecOpenStream(const char *filename) xmpsong = xmp_create_context(); int itsloaded = 0; - itsloaded = xmp_load_module_from_memory(xmpsong, buffer, 0); + itsloaded = xmp_load_module_from_memory(xmpsong, buffer, thelength); // Free our memory and close the file. Hunk_FreeTempMemory(buffer); FS_FCloseFile(file); // unfortunately these do not help with the leak if (itsloaded == 0) - itsloaded = xmp_start_player(xmpsong, xmpspeed, 0); // TODO: do sample rate of the mixer. + { + itsloaded = xmp_start_player(xmpsong, xmpspeed, 0); + startpat=s_xmp_startPattern->integer; + gopat = startpat; + fadey = 1.0; + xmp_set_player(xmpsong, XMP_PLAYER_VOLUME, 128); + xmp_set_position(xmpsong, startpat); + } if (itsloaded == 0) { // Com_Printf("XMP loaded our buffer of the file %s which is %i long \n", filename, thelength); @@ -197,6 +230,8 @@ int S_XMP_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer) return 0; } + S_XMP_CheckForFade(); + return bytes; } diff --git a/code/client/snd_dma.c b/code/client/snd_dma.c index 0f7ec157..ec8596a9 100644 --- a/code/client/snd_dma.c +++ b/code/client/snd_dma.c @@ -576,6 +576,30 @@ static void S_Base_StartSoundEx( vec3_t origin, int entityNum, int entchannel, s } ch = s_channels; + + + // leilei - check if this sound is already playing and kill it + if (s_interrupts->integer == 1) + { + for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) { + if (ch->entnum == entityNum && ch->thesfx == sfx) + { + S_ChannelFree(ch); + } + } + } + + // leilei - check if this channel is being used, and kill that too + else if (s_interrupts->integer == 2) + { + for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) { + if (ch->entnum == entityNum && ch->entchannel == entchannel && ch->thesfx && (entchannel != CHAN_AUTO)) + { + S_ChannelFree(ch); + } + } + } + inplay = 0; for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) { if (ch->entnum == entityNum && ch->thesfx == sfx) { @@ -1408,9 +1432,11 @@ static void S_OpenBackgroundStream( const char *filename ) { return; } - if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) { - Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", filename ); - } +// leilei - commented out, as we have music beyond this rate, and this warning is meant for an older +// iteration of q3's sound engine that couldn't handle other rates. +// if(s_backgroundStream->info.channels != 2 || s_backgroundStream->info.rate != 22050) { +// Com_Printf(S_COLOR_YELLOW "WARNING: music file %s is not 22k stereo\n", filename ); +// } } diff --git a/code/client/snd_local.h b/code/client/snd_local.h index e0f5b1d0..61325d51 100644 --- a/code/client/snd_local.h +++ b/code/client/snd_local.h @@ -199,6 +199,8 @@ extern cvar_t *s_musicVolume; extern cvar_t *s_muted; extern cvar_t *s_doppler; +extern cvar_t *s_interrupts; + extern cvar_t *s_testsound; qboolean S_LoadSound( sfx_t *sfx ); @@ -239,6 +241,8 @@ extern short *sfxScratchBuffer; extern sfx_t *sfxScratchPointer; extern int sfxScratchIndex; +extern cvar_t *s_xmp_startPattern; + qboolean S_Base_Init( soundInterface_t *si ); // OpenAL stuff diff --git a/code/client/snd_main.c b/code/client/snd_main.c index 91ab161c..b1504b7b 100644 --- a/code/client/snd_main.c +++ b/code/client/snd_main.c @@ -34,6 +34,9 @@ cvar_t *s_backend; cvar_t *s_muteWhenMinimized; cvar_t *s_muteWhenUnfocused; +cvar_t *s_interrupts; +cvar_t *s_xmp_startPattern; + static soundInterface_t si; /* @@ -485,9 +488,10 @@ void S_Init( void ) s_muted = Cvar_Get("s_muted", "0", CVAR_ROM); s_doppler = Cvar_Get( "s_doppler", "1", CVAR_ARCHIVE ); s_backend = Cvar_Get( "s_backend", "", CVAR_ROM ); + s_interrupts = Cvar_Get( "s_interrupts", "0", CVAR_ARCHIVE ); // leilei - pre-1.25 sound behavior s_muteWhenMinimized = Cvar_Get( "s_muteWhenMinimized", "0", CVAR_ARCHIVE ); s_muteWhenUnfocused = Cvar_Get( "s_muteWhenUnfocused", "0", CVAR_ARCHIVE ); - + s_xmp_startPattern = Cvar_Get( "s_xmp_startPattern", "0", CVAR_CHEAT ); // leilei - starting pattern for song cv = Cvar_Get( "s_initsound", "1", 0 ); if( !cv->integer ) { Com_Printf( "Sound disabled.\n" ); diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index ff6f1ee0..73c2be83 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // A user mod should never modify this file #ifdef STANDALONE - #define PRODUCT_NAME "ioq3+oa" + #define PRODUCT_NAME "OpenArena" #define BASEGAME "baseoa" #define CLIENT_WINDOW_TITLE "OpenArena" #define CLIENT_WINDOW_MIN_TITLE "OA" diff --git a/code/qcommon/qfiles.h b/code/qcommon/qfiles.h index 3333d54e..9f2b5fb2 100644 --- a/code/qcommon/qfiles.h +++ b/code/qcommon/qfiles.h @@ -35,7 +35,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif // surface geometry should not exceed these limits -#define SHADER_MAX_VERTEXES 4000 +#define SHADER_MAX_VERTEXES 1000 #define SHADER_MAX_INDEXES (6*SHADER_MAX_VERTEXES) diff --git a/code/renderer_oa/tr_backend.c b/code/renderer_oa/tr_backend.c index 9e53eee2..ff445975 100644 --- a/code/renderer_oa/tr_backend.c +++ b/code/renderer_oa/tr_backend.c @@ -1062,9 +1062,6 @@ RB_SetGL2D ================ */ -extern int tvWidth; -extern int tvHeight; - extern int vresWidth; extern int vresHeight; @@ -1456,148 +1453,6 @@ const void *RB_ClearDepth(const void *data) return (const void *)(cmd + 1); } - -extern cvar_t *r_slowness; // leilei - experimental variable slowness -extern cvar_t *r_slowness_cpu; // leilei - experimental variable slowness -extern cvar_t *r_slowness_gpu; // leilei - experimental variable slowness - -// leilei - motion blur hack -float motiontime; -float motion_finished; -int motionframe; -int motionpasses; -int numofmotionpasses; -int inmotion; - -int mblurred; // tells the renderer if we are rendering to a motion blur accum buffer instead of our drawing buffer -int mpasses; // how many passes of motion blur we should render. - -float motioner; - -void R_TVScreen( void ); -void R_RetroAAScreen( void ); - -void R_MblurScreen( void ); -void R_MblurScreenPost( void ); -void RB_UpdateMotionBlur (void){ - // leilei - motion blur hack - numofmotionpasses = 4; - numofmotionpasses = backEnd.refdef.time - backEnd.refdef.floatTime / 1000.0f; - - motioner = (backEnd.refdef.time - motiontime); - numofmotionpasses = (int)motioner / 3; - - - - // unfortunately doing this with some math just causes it to loop - if (numofmotionpasses == 4) numofmotionpasses = 0; - else if (numofmotionpasses == 3) numofmotionpasses = 1; - else if (numofmotionpasses == 2) numofmotionpasses = 2; - else if (numofmotionpasses == 1) numofmotionpasses = 3; - else if (numofmotionpasses == 0) numofmotionpasses = 4; - //else numofmotionpasses = 0; - - //ri.Printf( PRINT_WARNING, "hah %i\n", numofmotionpasses); - mpasses = floor(numofmotionpasses); - if (mpasses > 4) mpasses = 4; - if (mpasses < 1) return; // JUST DONT!! - motion_finished = (1000.0f / r_motionblur_fps->integer / 5 / mpasses); - - - if (motionpasses > numofmotionpasses){ - motionpasses = 0; - } - - if (motionframe > 5){ - - // do an accumulating post process - motionpasses += 1; - // R_MotionBlur_BackupScreen(10 + motionpasses); - R_MotionBlur_BackupScreen(11); // back it up in there... - motionframe = 1; - //return; - } - - if (backEnd.refdef.time > motiontime){ - R_MotionBlur_BackupScreen(motionframe); // back it up in there... - motionframe += 1; - R_MblurScreen(); - motiontime = backEnd.refdef.time + motion_finished; - inmotion = 1; - - } - else - inmotion = 0; -} - - -float mtime; // motion blur frame time - -// -// leilei - accumulation buffer-based motion blur, a much more legacy technique -// code addapted from MH's "Quake motion blur" thread (which is intended for GLQuake) -// but made to work with our cvars relating to the crappy pixel shader'd motion blur -// i coded on a whim one day. -// - -float mblur_time; -float mblur_timelast; - -float time_now; -float time_last; -float mbluracc; -int mblurredframes; -int mblurredframestotal; -void RB_AccumBlurValue (void) -{ - // calculate how much we need, determined by motion blur fps - mblur_time = time_now - time_last; - mbluracc = (mblur_time) / 32; - mbluracc *= -1; - mbluracc += 1.0f; - mbluracc /= 2; -}; - -void RB_DrawAccumBlur (void) -{ - static int blurstate = 0; - float accblur; - - if (r_tvMode->integer > -1) return; // tvmode causes this to crash - if (!r_motionblur->integer) return; - if (r_motionblur->integer > 1) return; // don't do it for the other motion blur techniques - - RB_AccumBlurValue (); - accblur = mbluracc; - - //ri.Printf( PRINT_WARNING, "accum value %f\n", mbluracc ); -// if (accblur > 1.0f) -// accblur = 0.5f; - - if (accblur <= 0.0f) - { - // reinit if we're not blurring so that the contents of the - // accumulation buffer are valid for the frame - blurstate = 0; - return; - } - - if (!blurstate) - { - // load the scene into the accumulation buffer - qglAccum (GL_LOAD, 1.0f); - } - else - { - qglAccum (GL_LOAD, 1.0f); - qglAccum (GL_MULT, accblur); // scale contents of accumulation buffer - qglAccum (GL_ACCUM, 1.0f - accblur); // add screen contents - qglAccum (GL_RETURN, 1.0f); // read result back - } - - blurstate = 1; -} - /* ============= RB_SwapBuffers @@ -1613,15 +1468,6 @@ const void *RB_SwapBuffers( const void *data ) { RB_EndSurface(); } - if (r_motionblur->integer > 2){ - { - mtime = backEnd.refdef.time + (1000.0f / r_motionblur_fps->integer); - mblurred = 0; - RB_UpdateMotionBlur(); - } - } - - // texture swapping test if ( r_showImages->integer ) { RB_ShowImages(); @@ -1638,21 +1484,8 @@ const void *RB_SwapBuffers( const void *data ) { } - if (r_motionblur->integer == 1){ - RB_DrawAccumBlur (); - - } - - - R_BrightScreen(); // leilei - alternate brightness - do it here so we hit evereything that represents our video buffer - R_RetroAAScreen(); // leilei - then apply 'anti aliasing' (hint: IT'S NOT really antialiasing) - R_PaletteScreen(); // leilei - then we palette our overbrighted antialiased screen. - R_NTSCScreen(); // leilei - then we get it through a DAC, degrading our precious VGA signals - R_TVScreen(); // leilei - tv operation comes last, this is a SCREEN - - cmd = (const swapBuffersCommand_t *)data; // we measure overdraw by reading back the stencil buffer and @@ -1689,17 +1522,11 @@ const void *RB_SwapBuffers( const void *data ) { backEnd.donewater = qfalse; backEnd.donepostproc = qfalse; backEnd.doneAltBrightness = qfalse; - backEnd.doneFilm = qfalse; backEnd.doneleifx = qfalse; - backEnd.doneanime = qfalse; backEnd.donepalette = qfalse; - backEnd.donemblur = qfalse; backEnd.doneSurfaces = qfalse; backEnd.doneSun = qfalse; backEnd.doneSunFlare = qfalse; - backEnd.donentsc = qfalse; - backEnd.donetv = qfalse; - backEnd.doneraa = qfalse; backEnd.doneParticles = qfalse; // leilei - only reset this every 15hz to keep it fast and synchronized @@ -1707,35 +1534,7 @@ const void *RB_SwapBuffers( const void *data ) { backEnd.doneFlareTests = qfalse; backEnd.flareTestTime = backEnd.refdef.time + 100.0f; } - - // leilei - artificial slowness (mapper debug) - this might be windows only -#ifdef _WIN32 - - if (r_slowness->integer > 2){ - // Should be roughly equiv to a P2 300 at value 1.0 (target system) - float cpuspeed = r_slowness_cpu->value; - float gpuspeed = r_slowness_gpu->value; - - if (cpuspeed < 1) cpuspeed = 1; - if (gpuspeed < 1) gpuspeed = 1; // avoid div0 - - float slowit = (float)(((float)(backEnd.pc.c_surfaces) / 16) + ((float)backEnd.pc.c_vertexes / 64) + 5400.0f); - slowit /= cpuspeed; // yeah it's the cpu - float blowit = ((float)(backEnd.pc.c_surfaces / 32) + (backEnd.pc.c_indexes / 1324 * (float)(glConfig.vidWidth * glConfig.vidHeight / 1100))); - blowit /= gpuspeed; // yeah it's the gpu - - if (blowit > slowit) slowit = blowit; // GPU bottleneck - else if (slowit > blowit) blowit = slowit; // CPU bottlebeck - - if (slowit > 8500) slowit = 8500; // but not too much? - Sleep(slowit); // FORCE A SLEEP!! HAHAHAHA!!! - - } -#endif - - - time_last = backEnd.refdef.time; return (const void *)(cmd + 1); } @@ -1748,7 +1547,6 @@ void RB_ExecuteRenderCommands( const void *data ) { int t1, t2; t1 = ri.Milliseconds (); - time_now = t1; while ( 1 ) { data = PADP(data, sizeof(void *)); @@ -1762,7 +1560,6 @@ void RB_ExecuteRenderCommands( const void *data ) { leifxmode = 0; R_PostprocessScreen(); R_BloomScreen(); - R_FilmScreen(); data = RB_StretchPic( data ); break; case RC_DRAW_SURFS: @@ -1776,7 +1573,6 @@ void RB_ExecuteRenderCommands( const void *data ) { leifxmode = 0; R_PostprocessScreen(); R_BloomScreen(); - R_FilmScreen(); data = RB_SwapBuffers( data ); break; case RC_SCREENSHOT: diff --git a/code/renderer_oa/tr_bloom.c b/code/renderer_oa/tr_bloom.c index e359e90b..46068da6 100644 --- a/code/renderer_oa/tr_bloom.c +++ b/code/renderer_oa/tr_bloom.c @@ -67,85 +67,17 @@ static struct { struct { int width, height; } work; - - // leilei - motion blur - struct { - image_t *texture; - int width, height; - float readW, readH; - } motion1; - struct { - image_t *texture; - int width, height; - float readW, readH; - } motion2; - struct { - image_t *texture; - int width, height; - float readW, readH; - } motion3; - struct { - image_t *texture; - int width, height; - float readW, readH; - } motion4; - struct { - image_t *texture; - int width, height; - float readW, readH; - } motion5; - struct { - image_t *texture; - int width, height; - float readW, readH; - } mpass1; - struct { - image_t *texture; - int width, height; - float readW, readH; - } mpass2; - struct { - image_t *texture; - int width, height; - float readW, readH; - } mpass3; - - struct { - image_t *texture; - int width, height; - float readW, readH; - } mpass4; - struct { - image_t *texture; - int width, height; - float readW, readH; - } tv; - struct { - int width, height; - } tvwork; - struct { - image_t *texture; - int width, height; - float readW, readH; - } tveffect; - qboolean started; #endif } postproc; -cvar_t *r_film; extern int force32upload; int leifxmode; int leifxpass; int fakeit = 0; -extern int tvinterlace; -int tvinter= 1; -extern int tvWidth; -extern int tvHeight; -extern float tvAspectW; // aspect correction extern int vresWidth; extern int vresHeight; /* @@ -671,96 +603,6 @@ Restore the temporary framebuffer section we used with the backup texture */ extern int mpasses; -static void ID_INLINE R_Bloom_QuadTV( int width, int height, float texX, float texY, float texWidth, float texHeight, int aa ) -{ - float aspcenter = 0; - float raa = r_retroAA->value; - if (raa < 1) raa = 1; - - float xpix = 1.0f / width / (4 / raa); - float ypix = 1.0f / height / (4 / raa); - float xaa; - float yaa; - int x = 0; - int y = 0; - - - - - if (aa == 0) { - xaa = 0; - yaa = 0; - } - if (aa == 1) { - xaa = -xpix; - yaa = ypix; - } - if (aa == 2) { - xaa = -xpix; - yaa = -ypix; - } - if (aa == 3) { - xaa = xpix; - yaa = -ypix; - } - if (aa == 4) { - xaa = xpix; - yaa = ypix; - } - - - - //y += tvHeight - height; - width += x; - height += y; - - texWidth += texX; - texHeight += texY; - - if (tvAspectW != 1.0) { - aspcenter = tvWidth * ((1.0f - tvAspectW) / 2); - // leilei - also do a quad that is 100% black, hiding our actual rendered viewport - - // qglViewport (0, 0, tvWidth, tvHeight ); - // qglScissor (0, 0, tvWidth, tvHeight ); - qglBegin( GL_QUADS ); - if (r_tvFilter->integer) { // bilinear filter - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - } - else { - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); - qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - } - qglColor4f( 0.0, 0.0, 0.0, 1 ); - qglVertex2f(0,0 ); - qglVertex2f(0,height); - qglVertex2f(width,height); - qglVertex2f(width,0); - qglEnd (); - qglColor4f( 1.0, 1.0, 1.0, 1 ); - } - - if (!aa) { - qglViewport(aspcenter, 0, (tvWidth * tvAspectW), tvHeight ); - qglScissor(aspcenter, 0, (tvWidth * tvAspectW), tvHeight ); - } - qglBegin( GL_QUADS ); - //GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - if (aa) - qglColor4f( 0.25, 0.25, 0.25, 1 ); - qglTexCoord2f( texX + xaa, texHeight + yaa); - qglVertex2f( x, y ); - qglTexCoord2f( texX + xaa, texY + yaa ); - qglVertex2f( x, height ); - qglTexCoord2f( texWidth + xaa, texY + yaa ); - qglVertex2f( width, height ); - qglTexCoord2f( texWidth + xaa, texHeight + yaa ); - qglVertex2f( width, y ); - qglEnd (); -} - - static void R_Bloom_RestoreScreen_Postprocessed( void ) { #ifdef GLSL_POSTPROCESSING @@ -778,51 +620,10 @@ static void R_Bloom_RestoreScreen_Postprocessed( void ) if (vertexShaders) R_GLSL_UseProgram(tr.leiFXFilterProgram); program=tr.programs[tr.leiFXFilterProgram]; } - if (leifxmode == 888) { - if (vertexShaders) R_GLSL_UseProgram(tr.animeProgram); - program=tr.programs[tr.animeProgram]; - } - if (leifxmode == 999) { - if (vertexShaders) R_GLSL_UseProgram(tr.animeFilmProgram); - program=tr.programs[tr.animeFilmProgram]; - } - if (leifxmode == 777) { - if (vertexShaders) R_GLSL_UseProgram(tr.motionBlurProgram); - program=tr.programs[tr.motionBlurProgram]; - } - if (leifxmode == 778) { - if (vertexShaders) R_GLSL_UseProgram(tr.motionBlurProgram); - program=tr.programs[tr.motionBlurProgram]; - } - if (leifxmode == 779) { - if (vertexShaders) R_GLSL_UseProgram(tr.motionBlurPostProgram); - program=tr.programs[tr.motionBlurPostProgram]; - } - if (leifxmode == 632) { - if (vertexShaders) R_GLSL_UseProgram(tr.NTSCEncodeProgram); - program=tr.programs[tr.NTSCEncodeProgram]; - } - if (leifxmode == 633) { - if (vertexShaders) R_GLSL_UseProgram(tr.NTSCDecodeProgram); - program=tr.programs[tr.NTSCDecodeProgram]; - } - if (leifxmode == 634) { - if (vertexShaders) R_GLSL_UseProgram(tr.NTSCBleedProgram); - program=tr.programs[tr.NTSCBleedProgram]; - } if (leifxmode == 666) { if (vertexShaders) R_GLSL_UseProgram(tr.BrightnessProgram); program=tr.programs[tr.BrightnessProgram]; } - if (leifxmode == 1236) { - if (vertexShaders) R_GLSL_UseProgram(tr.CRTProgram); - program=tr.programs[tr.CRTProgram]; - } - if (leifxmode == 1997) { - if (vertexShaders) R_GLSL_UseProgram(tr.paletteProgram); - program=tr.programs[tr.paletteProgram]; - } - } else { if (vertexShaders) R_GLSL_UseProgram(tr.postprocessingProgram); @@ -842,10 +643,6 @@ static void R_Bloom_RestoreScreen_Postprocessed( void ) if (program->u_ScreenToNextPixelY > -1) R_GLSL_SetUniform_u_ScreenToNextPixelY(program, (float)1.0/(float)glConfig.vidHeight); - // leilei - for TV shaders - if (program->u_ActualScreenSizeX > -1) R_GLSL_SetUniform_u_ActualScreenSizeX(program, tvWidth); - if (program->u_ActualScreenSizeY > -1) R_GLSL_SetUniform_u_ActualScreenSizeY(program, tvHeight); - //if (program->u_Time > -1) R_GLSL_SetUniform_Time(program, backEnd.refdef.time); if (program->u_Time > -1) R_GLSL_SetUniform_Time(program, ScreenFrameCount); @@ -869,68 +666,12 @@ static void R_Bloom_RestoreScreen_Postprocessed( void ) GL_SelectTexture(7); GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); GL_Bind( postproc.depth.texture ); - - // motion blur crap - if( r_motionblur->integer > 2) { - if (program->u_mpasses > -1) R_GLSL_SetUniform_u_mpasses(program, mpasses); - GL_SelectTexture(2); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.motion1.texture ); - GL_SelectTexture(3); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.motion2.texture ); - GL_SelectTexture(4); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.motion3.texture ); - GL_SelectTexture(5); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.motion4.texture ); - GL_SelectTexture(6); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.motion5.texture ); - GL_SelectTexture(11); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.mpass1.texture ); - GL_SelectTexture(12); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.mpass1.texture ); - GL_SelectTexture(13); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.mpass1.texture ); - GL_SelectTexture(14); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); - GL_Bind( postproc.mpass1.texture ); - } qglColor4f( 1, 1, 1, 1 ); // if (leifxmode == 778) // return; - if (leifxmode == 1234) { - { - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 0 ); - } - } - else if (leifxmode == 1236) { - { - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 0 ); - } - } - else if (leifxmode == 1233) { - - - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 1 ); - GL_SelectTexture(0); - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); - GL_Bind( postproc.screen.texture ); - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 2 ); - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 3 ); - R_Bloom_QuadTV( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH, 4 ); - - } - else { - R_Bloom_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, + R_Bloom_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, postproc.screen.readW,postproc.screen.readH ); - } if (vertexShaders) R_GLSL_UseProgram(0); GL_SelectTexture(0); #endif @@ -1122,21 +863,16 @@ static void R_Postprocess_InitTextures( void ) { #ifdef GLSL_POSTPROCESSING byte *data; - int intdiv = 1; force32upload = 1; // find closer power of 2 to screen size for (postproc.screen.width = 1; postproc.screen.width< glConfig.vidWidth; postproc.screen.width *= 2) {} -// if (r_tvMode->integer > 1) // interlaced // for (postproc.screen.height = 1;postproc.screen.height < vidinted;postproc.screen.height *= 2); //else for (postproc.screen.height = 1; postproc.screen.height < glConfig.vidHeight; postproc.screen.height *= 2) {} -// if (r_tvMode->integer > 1) -// intdiv = 2; - postproc.screen.readW = glConfig.vidWidth / (float)postproc.screen.width; postproc.screen.readH = glConfig.vidHeight / (float)postproc.screen.height; @@ -1153,9 +889,6 @@ static void R_Postprocess_InitTextures( void ) postproc.effect.readW = postproc.work.width / (float)postproc.effect.width; postproc.effect.readH = postproc.work.height / (float)postproc.effect.height; -// postproc.screen.readH /= intdiv; // interlacey - - // disable blooms if we can't handle a texture of that size if( postproc.screen.width > glConfig.maxTextureSize || postproc.screen.height > glConfig.maxTextureSize @@ -1172,62 +905,6 @@ static void R_Postprocess_InitTextures( void ) Com_Memset( data, 0, postproc.screen.width * postproc.screen.height * 4 ); postproc.screen.texture = R_CreateImage( "***postproc screen texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); ri.Hunk_FreeTempMemory( data ); - - // leilei - tv output texture - - if (r_tvMode->integer > -1) { - // find closer power of 2 to screen size - for (postproc.tv.width = 1; postproc.tv.width< tvWidth; postproc.tv.width *= 2); - for (postproc.tv.height = 1; postproc.tv.height < tvHeight; postproc.tv.height *= 2); - - //postproc.tv.height /= intdiv; // interlacey - - - postproc.tv.readW = tvWidth / (float)postproc.tv.width; - postproc.tv.readH = tvHeight / (float)postproc.tv.height; - - // find closer power of 2 to effect size - postproc.tvwork.width = r_bloom_sample_size->integer; - postproc.tvwork.height = postproc.tvwork.width * ( tvWidth / tvHeight ); - - // postproc.tvwork.height /= intdiv; // interlacey - - for (postproc.tveffect.width = 1; postproc.tveffect.width < postproc.tvwork.width; postproc.tveffect.width *= 2) {} - if (intdiv > 1) { - for (postproc.tveffect.height = 1; (postproc.tveffect.height/2) < postproc.tvwork.height; postproc.tveffect.height *= 2) {} - } - else { - for (postproc.tveffect.height = 1; postproc.tveffect.height < postproc.tvwork.height; postproc.tveffect.height *= 2) {} - } - - postproc.tveffect.readW = postproc.tvwork.width / (float)postproc.tveffect.width; - postproc.tveffect.readH = postproc.tvwork.height / (float)postproc.tveffect.height; - - - - data = ri.Hunk_AllocateTempMemory( tvWidth * tvHeight * 4 ); - Com_Memset( data, 0, tvWidth * tvHeight * 4 ); - postproc.tv.texture = R_CreateImage( "***tv output screen texture***", data, tvWidth, tvHeight, 0, 0, GL_CLAMP_TO_EDGE ); - ri.Hunk_FreeTempMemory( data ); - } - - // leilei - motion blur textures! - - if (r_motionblur->integer > 2) { - data = ri.Hunk_AllocateTempMemory( postproc.screen.width * postproc.screen.height * 4 ); - Com_Memset( data, 0, postproc.screen.width * postproc.screen.height * 4 ); - postproc.motion1.texture = R_CreateImage( "***motionblur1 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.motion2.texture = R_CreateImage( "***motionblur2 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.motion3.texture = R_CreateImage( "***motionblur3 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.motion4.texture = R_CreateImage( "***motionblur4 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.motion5.texture = R_CreateImage( "***motionblur5 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.mpass1.texture = R_CreateImage( "***motionaccum1 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.mpass2.texture = R_CreateImage( "***motionaccum1 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.mpass3.texture = R_CreateImage( "***motionaccum1 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - postproc.mpass4.texture = R_CreateImage( "***motionaccum1 texture***", data, postproc.screen.width, postproc.screen.height, 0, 0, GL_CLAMP_TO_EDGE ); - ri.Hunk_FreeTempMemory( data ); - } - // GLSL Depth Buffer data = ri.Hunk_AllocateTempMemory( postproc.screen.width * postproc.screen.height *4); @@ -1469,119 +1146,6 @@ void R_LeiFXPostprocessFilterScreen( void ) } - -// ================================================================= -// NTSC EFFECTS -// -// Thanks to the libretro team for their gpl ntsc shader code -// -// ================================================================= - - - -void R_NTSCScreen( void ) -{ -#ifdef GLSL_POSTPROCESSING - if( !r_ntsc->integer) - return; - if ( backEnd.donentsc) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this -// if ( !backEnd.doneSurfaces ) -// return; - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - if ( !backEnd.projection2D ) { - RB_SetGL2D(); - } - force32upload = 1; - - int ntsc_bleed = 0; - int ntsc_encode = 0; - int ntsc_decode = 0; - - // TODO: Switch it up - if (r_ntsc->integer == 1) { - ntsc_bleed = 1; - } - else if (r_ntsc->integer == 2) { - ntsc_bleed = 1; - ntsc_encode = 1; - ntsc_decode = 1; - } - else if (r_ntsc->integer == 3) { - ntsc_bleed = 0; - ntsc_encode = 1; - ntsc_decode = 1; - } - else if (r_ntsc->integer == 4) { - ntsc_bleed = 1; - ntsc_encode = 1; - ntsc_decode = 1; - } - else if (r_ntsc->integer > 6) { - ntsc_bleed = 666; - ntsc_encode = 0; - ntsc_decode = 0; - } - else { - ntsc_bleed = 0; - ntsc_encode = 1; - ntsc_decode = 0; - } - - - -// qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); -// qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); - - R_LeiFX_Stupid_Hack(); - if (ntsc_encode) { - leifxmode = 632; // Encode to composite - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - } - - - if (ntsc_decode) { - leifxmode = 633; // Decode to RGB - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - } - - if (ntsc_bleed) { - leifxmode = 634; // Encode to YUV and decode to RGB - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - } - - - - if (ntsc_bleed == 666) { - leifxmode = 634; // Encode to YUV and decode to RGB EXCESSIVELY - int passasses = r_ntsc->integer; - int j; - for (j=0; jinteger ) - return; - if ( backEnd.doneFilm ) - return; - if ( !backEnd.projection2D ) - RB_SetGL2D(); - backEnd.doneFilm = qtrue; - - // set up our colors, this is our default - tone[0] = 0.8f; - tone[1] = 0.9f; - tone[2] = 1.0f; - //VectorCopy( backEnd.currentEntity->ambientLight, tone ); - if (backEnd.currentEntity) { - if (backEnd.currentEntity->ambientLight[0] > 0.001f && backEnd.currentEntity->ambientLight[1] > 0.001f && backEnd.currentEntity->ambientLight[2] > 0.001f) { - tone[0] = backEnd.currentEntity->ambientLight[0]; - tone[1] = backEnd.currentEntity->ambientLight[1]; - tone[2] = backEnd.currentEntity->ambientLight[2]; - } - } - - // VectorNormalize(tone); - - tone[0] *= 0.3 + 0.7; - tone[1] *= 0.3 + 0.7; - tone[2] *= 0.3 + 0.7; - - // tone[0] = 1.6f; - // tone[1] = 1.2f; - // tone[2] = 0.7f; - - - // TODO: Get overexposure to flares raising this faking "HDR" - tonecont[0] = 0.0f; - tonecont[1] = 0.0f; - tonecont[2] = 0.0f; - - - // inverted - - toneinv[0] = tone[0] * -1 + 1 + tonecont[0]; - toneinv[1] = tone[1] * -1 + 1 + tonecont[1]; - toneinv[2] = tone[2] * -1 + 1 + tonecont[2]; - - // darken vignette. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); - GL_Bind( tr.dlightImage ); - GL_Cull( CT_TWO_SIDED ); - qglColor4f( 0.941177, 0.952941, 0.968628, 1.0f ); - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0.35f, 0.35f, 0.2f, 0.2f ); - - - - // brighten. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE); - GL_Bind( tr.dlightImage ); - GL_Cull( CT_TWO_SIDED ); - //qglColor4f( 0.941177, 0.952941, 0.968628, 1.0f ); - qglColor4f( (0.9f + (tone[0] * 0.5)), (0.9f + (tone[1] * 0.5)), (0.9f + (tone[2] * 0.5)), 1.0f ); - - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0.25f, 0.25f, 0.48f, 0.48f ); - - // invert. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE_MINUS_DST_COLOR | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); - GL_Bind( tr.whiteImage ); - GL_Cull( CT_TWO_SIDED ); - // qglColor4f(0.85098, 0.85098, 0.815686, 1.0f ); - qglColor4f( (0.8f + (toneinv[0] * 0.5)), (0.8f + (toneinv[1] * 0.5)), (0.8f + (toneinv[2] * 0.5)), 1.0f ); - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, 1 ); - - // brighten. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR); - GL_Bind( tr.whiteImage ); - GL_Cull( CT_TWO_SIDED ); - qglColor4f( 0.615686, 0.615686, 0.615686, 1.0f ); - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, 1 ); - - - // invoort. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_ONE_MINUS_DST_COLOR | GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); - GL_Bind( tr.whiteImage ); - GL_Cull( CT_TWO_SIDED ); - qglColor4f(1.0f, 1.0f, 1.0f , 1.0f ); - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, 1 ); - - // brighten. - GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR); - GL_Bind( tr.whiteImage ); - GL_Cull( CT_TWO_SIDED ); - // qglColor4f( 0.866667, 0.847059, 0.776471, 1.0f ); - qglColor4f( (0.73f + (toneinv[0] * 0.4)), (0.73f + (toneinv[1] * 0.4)), (0.73f + (toneinv[2] * 0.4)), 1.0f ); - R_Brighter_Quad( glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, 1 ); -} - - - - - -// ================================================================= -// OLD-STYLE ANTIALIASING -// ================================================================= - - - -// leilei - old 2000 console-style antialiasing/antiflickering -void R_RetroAAScreen( void ) -{ - // this should not need glsl either, but -#ifdef GLSL_POSTPROCESSING - if( !r_retroAA->integer) - return; - if ( backEnd.doneraa) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - if ( !backEnd.projection2D ) - RB_SetGL2D(); - force32upload = 1; - - leifxmode = 1233; // just show it through to tvWidth/tvHeight - //R_Postprocess_BackupScreen(); - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - - backEnd.doneraa = qtrue; - - force32upload = 0; - -#endif -} - - - - - - - -// ================================================================= -// !GLSL! -// ANIME SHADERS -// ================================================================= - - - - - -void R_AnimeScreen( void ) -{ -#ifdef GLSL_POSTPROCESSING - if( !r_anime->integer) - return; - if ( backEnd.doneanime) - return; - if ( !backEnd.doneSurfaces ) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - if ( !backEnd.projection2D ) - RB_SetGL2D(); - - force32upload = 1; - - leifxmode = 888; // anime effect - outlines, desat, bloom and other crap to go with it - R_LeiFX_Stupid_Hack(); - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - leifxmode = 999; // film effect - to blur things slightly, and add some grain and chroma stuff - R_LeiFX_Stupid_Hack(); - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - backEnd.doneanime = qtrue; - - force32upload = 0; -#endif - -} - - - - - - - - -// ================================================================= -// !GLSL! -// MOTION BLUR EFFECT -// ================================================================= - - -// leilei - motion blur hack -void R_MotionBlur_BackupScreen(int which) -{ -#ifdef GLSL_POSTPROCESSING - if( r_motionblur->integer < 3) - return; - if (which == 1) { - GL_Bind( postproc.motion1.texture ); // gather thee samples - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 2) { - GL_Bind( postproc.motion2.texture ); - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 3) { - GL_Bind( postproc.motion3.texture ); - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 4) { - GL_Bind( postproc.motion4.texture ); - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 5) { - GL_Bind( postproc.motion5.texture ); - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 11) { - GL_Bind( postproc.mpass1.texture ); // to accum - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 12) { - GL_Bind( postproc.mpass1.texture ); // to accum - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 13) { - GL_Bind( postproc.mpass1.texture ); // to accum - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 14) { - GL_Bind( postproc.mpass1.texture ); // to accum - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } - if (which == 18) { - GL_Bind( postproc.screen.texture ); // to accum - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - } -#endif - -} - - -void R_MblurScreen( void ) -{ -#ifdef GLSL_POSTPROCESSING - if( r_motionblur->integer < 3) - return; - if ( backEnd.donemblur) - return; - if ( !backEnd.doneSurfaces ) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - if ( !backEnd.projection2D ) - RB_SetGL2D(); - - - - - force32upload = 1; - - leifxmode = 777; // accumulate frames for the motion blur buffer - R_LeiFX_Stupid_Hack(); - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - force32upload = 0; -#else - // NO! Use the accumulation buffer instead. -#endif -} - -void R_MblurScreenPost( void ) -{ -#ifdef GLSL_POSTPROCESSING - if( r_motionblur->integer < 3) - return; - if ( !backEnd.doneSurfaces ) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - backEnd.donemblur = qtrue; - - if ( !backEnd.projection2D ) - RB_SetGL2D(); - - force32upload = 1; - - leifxmode = 770; // accumulate frames for the motion blur buffer - R_LeiFX_Stupid_Hack(); -// R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - force32upload = 0; -#else - // NO! -#endif -} - - - -// ================================================================= -// TV MODE -// ================================================================= - -static void R_Postprocess_BackupScreenTV( void ) -{ -#ifdef GLSL_POSTPROCESSING - 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_Bind( postproc.screen.texture ); - qglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, glConfig.vidWidth, glConfig.vidHeight); -#endif -} - -static void R_Postprocess_ScaleTV( void ) -{ -#ifdef GLSL_POSTPROCESSING - - GL_TexEnv( GL_MODULATE ); - qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); - qglMatrixMode( GL_PROJECTION ); - qglLoadIdentity (); -#endif -} - - - -// tvmode doesn't do any actual postprocessing yet (ntsc, shadow mask etc) - -float tvtime; - -void R_TVScreen( void ) -{ - // leilei - this might not actually need glsl but we're doing this anyway. -#ifdef GLSL_POSTPROCESSING - if( r_tvMode->integer < 0) - return; - if ( backEnd.donetv) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - -// if ( !backEnd.projection2D ) -// RB_SetGL2D(); - - - - force32upload = 1; - -// postprocess = 1; - - if (backEnd.refdef.time > tvtime) { - tvinterlace *= -1; - tvtime = backEnd.refdef.time + (1000.0f / 60); // 60hz - } - - tvinter = tvinterlace; - if (tvinter < 0) tvinter = 0; - if (r_tvMode->integer < 100) tvinter = 0; - tvinter = 0; - - leifxmode = 1234; // just show it through to tvWidth/tvHeight - - //if (r_tvMode->integer > 2) - // leifxmode = 1236; // run it through a shader - //R_Postprocess_BackupScreen(); - - if (r_tvMode->integer > 100) { - R_Postprocess_ScaleTV(); - } - else { - R_Postprocess_BackupScreenTV(); - - R_Bloom_RestoreScreen_Postprocessed(); - } - - backEnd.donetv = qtrue; - - force32upload = 0; -#else - // NO! -#endif - -} - - - - - - -// ================================================================= -// PALLETIZING -// -// Processes the screen into having a 8-bit indexed color -// palette to suit a throwback mode better -// -// ================================================================= - - - - -void R_PaletteScreen( void ) -{ -#ifdef GLSL_POSTPROCESSING - if( !r_palletize->integer) - return; - if ( backEnd.donepalette) - return; - if ( !backEnd.doneSurfaces ) - return; - if ( !vertexShaders ) - return; // leilei - cards without support for this should not ever activate this - if( !postproc.started ) { - force32upload = 1; - R_Postprocess_InitTextures(); - if( !postproc.started ) - return; - } - - if ( !backEnd.projection2D ) - RB_SetGL2D(); - - force32upload = 1; - - leifxmode = 1997; // anime effect - outlines, desat, bloom and other crap to go with it - R_LeiFX_Stupid_Hack(); - R_Postprocess_BackupScreen(); - R_Bloom_RestoreScreen_Postprocessed(); - backEnd.donepalette = qtrue; - - force32upload = 0; - -#else - // NO! -#endif -} - - - - -// ================================================================= -// WATER BUFFER TEST -// ================================================================= - -#if 0 -static struct { - // NO! -} water; - -// leilei - experimental water effect -static void R_Water_InitTextures( void ) -{ - // NO! -} -#endif - - - -void R_InitWaterTextures( void ) -{ - // NO! -} - - -#if 0 -static void R_Water_BackupScreen( void ) -{ - // NO! -} - -static void R_WaterWorks( void ) -{ - // NO! -} - - -static void R_Water_RestoreScreen( void ) -{ - // NO! -} -#endif - -void R_WaterInit( void ) -{ - // NO! -} - - -void R_WaterScreen( void ) -{ - // NO! } diff --git a/code/renderer_oa/tr_bsp.c b/code/renderer_oa/tr_bsp.c index 646eb24d..d995c556 100644 --- a/code/renderer_oa/tr_bsp.c +++ b/code/renderer_oa/tr_bsp.c @@ -108,16 +108,69 @@ static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) { r = in[0] << shift; g = in[1] << shift; b = in[2] << shift; - - // normalize by color instead of saturating to white - if ( ( r | g | b ) > 255 ) { - int max; - max = r > g ? r : g; - max = max > b ? max : b; - r = r * 255 / max; - g = g * 255 / max; - b = b * 255 / max; + // leilei - handle light desaturation here instead, so we can also mono the lightgrid and have one less redundant clamp + if( r_monolightmaps->value > 0) + { + float saturated = (r * 0.22126) + (g * 0.7152) + (b * 0.0722); + float ml = r_monolightmaps->value; // sanitize + if (ml>1) ml=1; if (ml<0) ml=0; + r = saturated + (r - saturated) * ( 1-ml ); + g = saturated + (g - saturated) * ( 1-ml ); + b = saturated + (b - saturated) * ( 1-ml ); + } + + if (r_lightmapColorNorm->integer == 2) // leilei + { + float lum, invader = 0; + // get luma from base color + lum = (0.22126*r + 0.7152*g + 0.0722*b); // thanks wiki + + // normalize by color instead of saturating to white + if ( ( r | g | b ) > 255 ) { + + int max; + max = r > g ? r : g; + max = max > b ? max : b; + r = r * 255 / max; + g = g * 255 / max; + b = b * 255 / max; + + + invader = lum - (0.22126*r + 0.7152*g + 0.0722*b); // get the differences from the normalized color + invader *= (invader/255); + + r += invader; + g += invader; + b += invader; + + // Normalize... again!!! + + max = r > g ? r : g; + max = max > b ? max : b; + r = r * 255 / max; + g = g * 255 / max; + b = b * 255 / max; + } + } + else if (r_lightmapColorNorm->integer) // leilei - made this an option for trying normal clamp + { + // normalize by color instead of saturating to white + if ( ( r | g | b ) > 255 ) { + int max; + + max = r > g ? r : g; + max = max > b ? max : b; + r = r * 255 / max; + g = g * 255 / max; + b = b * 255 / max; + } + } + else + { + if ( r > 255 ) r = 255; + if ( g > 255 ) g = 255; + if ( b > 255 ) b = 255; } out[0] = r; @@ -299,7 +352,6 @@ static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) { // leilei - placeholder hack if (tr.placeholderTextureAvail == 1 && !Q_strncmp( dsh->shader, "textures", 8 )) { - // return tr.placeholderTextureShader; shader = R_FindShader( "placeholder_texture", lightmapNum, qtrue ); return shader; } diff --git a/code/renderer_oa/tr_extensions.c b/code/renderer_oa/tr_extensions.c index a63bc0a3..150d6609 100644 --- a/code/renderer_oa/tr_extensions.c +++ b/code/renderer_oa/tr_extensions.c @@ -126,6 +126,7 @@ typedef enum { int softwaremode; // leilei - detect for software mode int voodootype; // leilei - detect for voodoo revision +char extensions_string_full [BIG_INFO_STRING]; // leilei - gl extensions crash workaround /** From renderer_opengl2 (v28) */ static qboolean GLimp_HaveExtension(const char *ext) @@ -331,6 +332,11 @@ void GLimp_InitExtraExtensions() Q_strncpyz( buf, glConfig.renderer_string, sizeof(buf) ); Q_strlwr( buf ); + // leilei - we are done with our extensions string, if it's too long we can just trim it so we won't hardlock old qvms with an overflow. + Q_strncpyz( extensions_string_full, (char *) qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) ); // copy to a global for gfxinfo + char butt[640]; + Q_strncpyz( glConfig.extensions_string, (char *) qglGetString (GL_EXTENSIONS), sizeof( butt ) ); + // // this is where hardware specific workarounds that should be diff --git a/code/renderer_oa/tr_image.c b/code/renderer_oa/tr_image.c index ab60e48d..898e0a8c 100644 --- a/code/renderer_oa/tr_image.c +++ b/code/renderer_oa/tr_image.c @@ -213,18 +213,18 @@ void R_InitPalette( void ) { byte *buff; int i, v; - ri.Printf( PRINT_ALL, "INIT PALETTE......\n"); + ri.Printf( PRINT_ALL, "R_InitPalette: \n"); ri.FS_ReadFile("gfx/palette.lmp", (void **)&buff); if(!buff){ - ri.Printf( PRINT_ALL, "PALLETE FALED :(!\n" ); + ri.Printf( PRINT_ALL, "PALETTE FAILED\n" ); paletteavailable = 0; // Don't have a palette paletteenabled = 0; // Don't do 8-bit textures return; } palettemain = buff; - ri.Printf( PRINT_ALL, "PALETTE LOADDEEEED!!!!!!!!!!!!1\n" ); + ri.Printf( PRINT_ALL, "PALETTE LOADED\n" ); paletteavailable = 1; // Do have a palette if (palettedTextureSupport) { @@ -1033,79 +1033,6 @@ int hqresample = 0; // leilei - high quality texture resampling // Currently 0 as there is an alignment issue I haven't fixed. int isicon; // leilei - for determining if it's an icon. -char dumpname[ MAX_QPATH ]; // leilei - name for texture dumping - -static void DumpTex( unsigned *data, - int width, int height ) -{ - -// leilei - Do crazy dumping crap - byte *scan; - byte *baffer, *alffer, *flipper; - scan = ((byte *)data); - int padlen = 0; - int be, ber; - int scrale = width * height; - int hasalf = 0; - float countw = 0; -#if 0 - int scravg = width + height / 2; - int quality = 85; // estimate quality from total size - if (scravg > 511) quality = 42; // huge textures - else if (scravg > 255) quality = 62; // large textures - else if (scravg > 127) quality = 72; // large textures - else if (scravg < 127) quality = 95; // tiny textures -#endif - baffer = ri.Hunk_AllocateTempMemory( width * height * 3 ); - flipper = ri.Hunk_AllocateTempMemory( width * height * 3 ); - alffer = ri.Hunk_AllocateTempMemory( width * height * 3 ); - // TODO: Save alpha separately - // I'm gonna flip...... - int alfcnt = 0; - - - - for (be=0; be width) - countw = 0; - else - countw++; - ber = scrale - be - 1; - bib = be; - if (bib < 0) bib = 0; - if (bib > scrale) bib = 0; - baffer[bib*3] = scan[ber*4]; - baffer[bib*3+1] = scan[ber*4+1]; - baffer[bib*3+2] = scan[ber*4+2]; - alffer[bib*3] = scan[ber*4+3]; - alffer[bib*3+1] = scan[ber*4+3]; - alffer[bib*3+2] = scan[ber*4+3]; - if (scan[ber*4+3] > 1){ hasalf = 1;} - if (scan[ber*4+3] == 255){ alfcnt += 1; } - } - - - // NOW FIX IT - - - //memcount = (width * 3 + padlen) * height; - if ((width > 16) && (height > 16)){ - RE_SaveJPG( va("dump/%s.jpg", dumpname), 85,width, height, baffer, padlen); - if (hasalf) { - RE_SaveJPG( va("dump/%s_alpha.jpg", dumpname), 85,width, height, alffer, padlen); - } - } - ri.Printf( PRINT_ALL, "TEXDUMP: %s \n", dumpname ); - -// if ( baffer != 0 ) - ri.Hunk_FreeTempMemory( baffer ); -// if ( alffer != 0 ) - ri.Hunk_FreeTempMemory( alffer ); - ri.Hunk_FreeTempMemory( flipper ); -} - static void Upload32( unsigned *data, int width, int height, @@ -1129,9 +1056,6 @@ static void Upload32( unsigned *data, int forceBits = 0; - if (lightMap && r_parseStageSimple->integer) hackoperation = 4; - - // // convert to exact power of 2 sizes // @@ -1208,12 +1132,8 @@ static void Upload32( unsigned *data, // if ( isicon ){ - if (r_iconmip->integer){ - - // Auto-determine from resolution division - if (r_iconmip->integer == 1){ int wadth, haght, dev = 0; @@ -1266,8 +1186,6 @@ static void Upload32( unsigned *data, scaled_height = 1; } - - // // clamp to the current upper OpenGL limit // scale both axis down equally so we don't have to @@ -1301,7 +1219,6 @@ static void Upload32( unsigned *data, int r, g, b; vec3_t rgb; byte alfa = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]); - //byte alfa = (scan[i*4]+ scan[i*4 + 1]+ scan[i*4 + 2]) / 3; r = scan[i*4 + 0]; g = scan[i*4 + 1]; @@ -1409,152 +1326,11 @@ static void Upload32( unsigned *data, } - - if(r_textureDither->integer) // possibly the stupidest texture dithering ever - { -#ifdef DONTEVENTHINKABOUTTHIS - int passes = r_textureDither->integer; - int that; - /* LEIFX FILTER C PORT PROTOTYPE SCRATCH AREA - No vectors, only ints ints ints Obviously can be refactored with SSE */ -#define FILTCAP (0.075 * 255) -#define FILTCAPG (FILTCAP / 2) - for (that=0;that FILTCAP ) rd = FILTCAP; - if (gd > FILTCAPG) gd = FILTCAPG; - if (bd > FILTCAP ) bd = FILTCAP; - - if (rd < -FILTCAP ) rd = -FILTCAP; - if (gd < -FILTCAPG) gd = -FILTCAPG; - if (bd < -FILTCAP ) bd = -FILTCAP; - - /* Add our Differences */ - - r1 += (rd/3); - g1 += (gd/3); - b1 += (bd/3); - - /* Obligatory clamping part */ - if (r1 < 0) r1 = 0; - if (g1 < 0) g1 = 0; - if (b1 < 0) b1 = 0; - - if (r1 > 255) r1 = 255; - if (g1 > 255) g1 = 255; - if (b1 > 255) b1 = 255; - - if (r2 < 0) r2 = 0; - if (g2 < 0) g2 = 0; - if (b2 < 0) b2 = 0; - - if (r2 > 255) r2 = 255; - if (g2 > 255) g2 = 255; - if (b2 > 255) b2 = 255; - - - - /* Put processed image back into the buffer */ - scan[i*4] = r1; - scan[i*4 + 1] = g1; - scan[i*4 + 2] = b1; - - } - - } -#endif - - for ( i = 0; i < c; i++ ) - { - int ren = (crandom() * 4); - int rg,gg,bb; - rg = scan[i*4]; - gg = scan[i*4+1]; - bb = scan[i*4+2]; - - //if ((rg / 64) != ceil(rg / 64)) - rg = scan[i*4] + ren; - //if ((gg / 32) != ceil(gg / 32)) - gg = scan[i*4 + 1] + (ren / 2); - //if ((bb / 64) != ceil(bb / 64)) - bb = scan[i*4 + 2] + ren; - - if (rg < 0) rg = 0; - if (gg < 0) gg = 0; - if (bb < 0) bb = 0; - - if (rg > 255) rg = 255; - if (gg > 255) gg = 255; - if (bb > 255) bb = 255; - - scan[i*4] = rg; - scan[i*4 + 1] = gg; - scan[i*4 + 2] = bb; - } - - } - - - - - if( r_greyscale->value ) - { - // leilei - replaced with saturation processing - for ( i = 0; i < c; i++ ) - { - float saturated = (scan[i*4] * 0.333) + (scan[i*4 + 1] * 0.333) + (scan[i*4 + 2] * 0.333); - scan[i*4] = saturated + (scan[i*4] - saturated) * (1-r_greyscale->value); - scan[i*4 + 1] = saturated + (scan[i*4 + 1] - saturated) * (1-r_greyscale->value); - scan[i*4 + 2] = saturated + (scan[i*4 + 2] - saturated) * (1-r_greyscale->value); - - if (scan[i*4] > 255) scan[i*4] = 255; - if (scan[i*4 + 1] > 255) scan[i*4 + 1] = 255; - if (scan[i*4 + 2] > 255) scan[i*4 + 2] = 255; - } - } - if(lightMap) { - if( r_monolightmaps->value ) - { - for ( i = 0; i < c; i++ ) - { - float saturated = (scan[i*4] * 0.333) + (scan[i*4 + 1] * 0.333) + (scan[i*4 + 2] * 0.333); - scan[i*4] = saturated + (scan[i*4] - saturated) * (1-r_monolightmaps->value); - scan[i*4 + 1] = saturated + (scan[i*4 + 1] - saturated) * (1-r_monolightmaps->value ); - scan[i*4 + 2] = saturated + (scan[i*4 + 2] - saturated) * (1-r_monolightmaps->value ); - - if (scan[i*4] > 255) scan[i*4] = 255; - if (scan[i*4 + 1] > 255) scan[i*4 + 1] = 255; - if (scan[i*4 + 2] > 255) scan[i*4 + 2] = 255; - } - } - - if(r_greyscale->integer) - internalFormat = GL_LUMINANCE; - else if(r_monolightmaps->integer) + if(r_monolightmaps->integer) internalFormat = GL_LUMINANCE; else internalFormat = GL_RGB; @@ -1617,16 +1393,6 @@ static void Upload32( unsigned *data, // select proper internal format if ( samples == 3 ) { - if(r_greyscale->integer) - { - if(r_texturebits->integer == 16 || forceBits == 16) - internalFormat = GL_LUMINANCE8; - else if(r_texturebits->integer == 32 || forceBits == 32) - internalFormat = GL_LUMINANCE16; - else - internalFormat = GL_LUMINANCE; - } - else { if ( glConfig.textureCompression == TC_S3TC_ARB ) { @@ -1667,16 +1433,6 @@ static void Upload32( unsigned *data, } else if ( samples == 4 ) { - if(r_greyscale->integer) - { - if(r_texturebits->integer == 16 || forceBits == 16) - internalFormat = GL_LUMINANCE8_ALPHA8; - else if(r_texturebits->integer == 32 || forceBits == 32) - internalFormat = GL_LUMINANCE16_ALPHA16; - else - internalFormat = GL_LUMINANCE_ALPHA; - } - else { if ( glConfig.textureCompression == TC_S3TC_ARB ) { @@ -2218,12 +1974,6 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, GL_Bind(image); - // leilei - texture dumping - if (r_texdump->integer) { - COM_StripExtension( name, dumpname, MAX_QPATH ); // leilei - transfer name for texdump - DumpTex( (unsigned *)pic, image->width, image->height); - } - if (paletteavailable && r_texturebits->integer == 8 && !isLightmap && !depthimage && !force32upload) { Upload8( (unsigned *)pic, image->width, image->height, image->flags & IMGFLAG_MIPMAP, diff --git a/code/renderer_oa/tr_init.c b/code/renderer_oa/tr_init.c index 7a436b96..a1480830 100644 --- a/code/renderer_oa/tr_init.c +++ b/code/renderer_oa/tr_init.c @@ -71,7 +71,6 @@ cvar_t *r_skipBackEnd; cvar_t *r_stereoEnabled; cvar_t *r_anaglyphMode; -cvar_t *r_greyscale; cvar_t *r_monolightmaps; cvar_t *r_ignorehwgamma; @@ -196,7 +195,6 @@ cvar_t *r_flareMethod; // method of flare intensity cvar_t *r_flareQuality; // testing quality of the flares. cvar_t *r_flareSun; // type of flare to use for the sun cvar_t *r_flareDelay; // time delay for medium quality flare testing -cvar_t *r_flaresMotionBlur; // Stretch blur cvar_t *r_specMode; //cvar_t *r_waveMode; @@ -205,45 +203,31 @@ cvar_t *r_flaresDlightShrink; cvar_t *r_flaresDlightFade; cvar_t *r_flaresDlightOpacity; cvar_t *r_flaresDlightScale; + +cvar_t *r_lightmapColorNorm; + //cvar_t *r_flaresSurfradii; cvar_t *r_alternateBrightness; // leilei - linux overbright fix cvar_t *r_mockvr; // Leilei - for debugging PVR only! -cvar_t *r_parseStageSimple; // Leilei - for debugging PVR only! cvar_t *r_leifx; // Leilei - leifx nostalgia filter -cvar_t *r_modelshader; // Leilei +cvar_t *r_shadeMethod; // Leilei cvar_t *r_particles; // Leilei - particle effects motif -cvar_t *r_ntsc; // Leilei - ntsc / composite signals -//cvar_t *r_tvMode; // Leilei - tv fake mode -cvar_t *r_retroAA; // Leilei - old console AA -cvar_t *r_anime; // Leilei - anime filter -cvar_t *r_palletize; // Leilei - palletization +cvar_t *r_skytess; // leilei - lower detail of skies + cvar_t *r_leidebug; // Leilei - debug cvar_t *r_leidebugeye; // Leilei - eye debug cvar_t *r_suggestiveThemes; // leilei - mature content control -//cvar_t *r_motionblur; // Leilei - motionblur -cvar_t *r_motionblur_fps; // Leilei - motionblur framerated - -cvar_t *r_slowness; // Leilei - the cvar that slows everything down. use with caution. -cvar_t *r_slowness_cpu; // Leilei -cvar_t *r_slowness_gpu; // Leilei - cvar_t *r_textureDither; // leilei - Dithered texture -cvar_t *r_texdump; // Leilei - debug - texture dump as they load, players should never need to use this! - // leilei - fallback shader hack #ifdef USE_FALLBACK_GLSL -extern const char *fallbackShader_anime_vp; -extern const char *fallbackShader_anime_fp; -extern const char *fallbackShader_anime_film_vp; -extern const char *fallbackShader_anime_film_fp; extern const char *fallbackShader_brightness_vp; extern const char *fallbackShader_brightness_fp; extern const char *fallbackShader_leifx_dither_vp; @@ -254,10 +238,6 @@ extern const char *fallbackShader_leifx_gamma_vp; extern const char *fallbackShader_leifx_gamma_fp; extern const char *fallbackShader_leifx_vgasignal_vp; extern const char *fallbackShader_leifx_vgasignal_fp; -extern const char *fallbackShader_motionblur_accum_vp; -extern const char *fallbackShader_motionblur_accum_fp; -extern const char *fallbackShader_motionblur_post_vp; -extern const char *fallbackShader_motionblur_post_fp; #endif @@ -587,24 +567,12 @@ RB_TakeScreenshotCmd ================== */ -extern int tvWidth; -extern int tvHeight; - const void *RB_TakeScreenshotCmd( const void *data ) { const screenshotCommand_t *cmd; cmd = (const screenshotCommand_t *)data; - // leilei - hack for tvmode - if (r_tvMode->integer > -1) { - - if (cmd->jpeg) - RB_TakeScreenshotJPEG( cmd->x, cmd->y, tvWidth, tvHeight, cmd->fileName); - else - RB_TakeScreenshot( cmd->x, cmd->y, tvWidth, tvHeight, cmd->fileName); - } - if (cmd->jpeg) RB_TakeScreenshotJPEG( cmd->x, cmd->y, cmd->width, cmd->height, cmd->fileName); else @@ -1029,6 +997,7 @@ void R_PrintLongString(const char *string) GfxInfo_f ================ */ +extern char extensions_string_full [BIG_INFO_STRING]; // leilei - gl extensions crash workaround void GfxInfo_f( void ) { const char *enablestrings[] = { @@ -1044,7 +1013,7 @@ void GfxInfo_f( void ) 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: " ); - R_PrintLongString( glConfig.extensions_string ); + R_PrintLongString( extensions_string_full );//R_PrintLongString( glConfig.extensions_string ); // leilei - gl extensions crash workaround ri.Printf( PRINT_ALL, "\n" ); ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize ); ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_UNITS_ARB: %d\n", glConfig.numTextureUnits ); @@ -1202,10 +1171,9 @@ void R_Register( void ) r_subdivisions = ri.Cvar_Get ("r_subdivisions", "4", 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); - ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); - r_monolightmaps = ri.Cvar_Get("r_monolightmaps", "0", CVAR_ARCHIVE | CVAR_LATCH); + ri.Cvar_CheckRange(r_monolightmaps, 0, 1, qfalse); + // // temporary latched variables that can only change over a restart @@ -1262,6 +1230,7 @@ void R_Register( void ) r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT ); r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT ); r_lightmap = ri.Cvar_Get ("r_lightmap", "0", 0 ); + r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT ); @@ -1322,45 +1291,30 @@ void R_Register( void ) r_flareSun = ri.Cvar_Get( "r_flareSun", "0" , CVAR_ARCHIVE); // it's 0 because mappers expect 0. r_flareDelay = ri.Cvar_Get( "r_flareDelay", "100" , CVAR_CHEAT); // update delay for flare pixel read checking. - r_flaresMotionBlur = ri.Cvar_Get( "r_flaresMotionBlur", "0" , CVAR_ARCHIVE ); // fake motion blur on flares - - r_mockvr = ri.Cvar_Get( "r_mockvr", "0" , CVAR_CHEAT); - r_parseStageSimple = ri.Cvar_Get( "r_parseStageSimple", "0" , CVAR_CHEAT); r_leifx = ri.Cvar_Get( "r_leifx", "0" , CVAR_ARCHIVE | CVAR_LATCH); - r_modelshader = ri.Cvar_Get( "r_modelshader", "0" , CVAR_ARCHIVE | CVAR_LATCH); // leilei - load and use special shaders for lightDiffuse models + r_shadeMethod = ri.Cvar_Get( "r_shadeMethod", "0" , CVAR_ARCHIVE); // leilei - Alternative lightingDiffuse + + r_skytess = ri.Cvar_Get( "r_skyTess", "8", CVAR_ARCHIVE ); // leilei - sky detail adjustment + r_detailTextureScale = ri.Cvar_Get( "r_detailtextureScale", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - adjust scale of detail textures r_detailTextureLayers = ri.Cvar_Get( "r_detailtextureLayers", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - add more detail layers - r_ntsc = ri.Cvar_Get( "r_ntsc", "0" , CVAR_ARCHIVE | CVAR_LATCH); // leilei - ntsc filter - - //r_tvMode = ri.Cvar_Get( "r_tvMode", "0" , CVAR_ARCHIVE | CVAR_LATCH); - r_retroAA = ri.Cvar_Get( "r_retroAA", "0" , CVAR_ARCHIVE | CVAR_LATCH); - r_suggestiveThemes = ri.Cvar_Get( "r_suggestiveThemes", "1" , CVAR_ARCHIVE | CVAR_LATCH); -// r_motionblur = ri.Cvar_Get( "r_motionblur", "0" , CVAR_ARCHIVE | CVAR_LATCH); - r_motionblur_fps = ri.Cvar_Get( "r_motionblur_fps", "60", 0); - - r_anime = ri.Cvar_Get( "r_anime", "0" , CVAR_ARCHIVE | CVAR_LATCH); - r_palletize = ri.Cvar_Get( "r_palletize", "0" , CVAR_ARCHIVE | CVAR_LATCH); r_leidebug = ri.Cvar_Get( "r_leidebug", "0" , CVAR_CHEAT); r_particles = ri.Cvar_Get( "r_particles", "0" , CVAR_ARCHIVE | CVAR_LATCH); r_leidebugeye = ri.Cvar_Get( "r_leidebugeye", "0" , CVAR_CHEAT); - r_slowness = ri.Cvar_Get( "r_slowness", "0" , CVAR_ARCHIVE); // it's 0 because you want it to be the fastest possible by default. - r_slowness_cpu = ri.Cvar_Get( "r_slowness_cpu", "300" , CVAR_ARCHIVE); // it's 0 because you want it to be the fastest possible by default. - r_slowness_gpu = ri.Cvar_Get( "r_slowness_gpu", "96" , CVAR_ARCHIVE); // it's 0 because you want it to be the fastest possible by default. r_iconmip = ri.Cvar_Get ("r_iconmip", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - icon mip r_iconBits = ri.Cvar_Get ("r_iconBits", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - icon bits r_lightmapBits = ri.Cvar_Get ("r_lightmapBits", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - lightmap color bits + r_lightmapColorNorm = ri.Cvar_Get ("r_lightmapColorNorm", "1", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - lightmap color normalization r_textureDither = ri.Cvar_Get ("r_textureDither", "0", CVAR_ARCHIVE | CVAR_LATCH ); // leilei - dithered textures - r_texdump = ri.Cvar_Get( "r_texdump", "0", CVAR_CHEAT ); // leilei - debug - texture dumping - // make sure all the commands added here are also // removed in R_Shutdown ri.Cmd_AddCommand( "imagelist", R_ImageList_f ); @@ -1422,12 +1376,6 @@ static glslProgram_t *R_GLSL_AllocProgram(void) program->u_ViewOrigin = -1; program->u_Normal = -1; - program->u_mpass1 = -1; - program->u_mpass2 = -1; - program->u_mpass3 = -1; - program->u_mpass4 = -1; - - program->rubyTextureSize = -1; program->rubyInputSize = -1; program->rubyOutputSize = -1; @@ -1489,21 +1437,6 @@ void R_GLSL_Init(void) Q_strncpyz(programFragmentObjects[0], "glsl/sky_fp.glsl", sizeof(programFragmentObjects[0])); tr.skyProgram = RE_GLSL_RegisterProgram("sky", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - - Q_strncpyz(programVertexObjects[0], "glsl/anime_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/anime_fp.glsl", sizeof(programFragmentObjects[0])); - tr.animeProgram = RE_GLSL_RegisterProgram("anime", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - Q_strncpyz(programVertexObjects[0], "glsl/anime_film_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/anime_film_fp.glsl", sizeof(programFragmentObjects[0])); - tr.animeFilmProgram = RE_GLSL_RegisterProgram("anime_film", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - Q_strncpyz(programVertexObjects[0], "glsl/palette_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/palette_fp.glsl", sizeof(programFragmentObjects[0])); - tr.paletteProgram = RE_GLSL_RegisterProgram("palette", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - Q_strncpyz(programVertexObjects[0], "glsl/leifx_dither_vp.glsl", sizeof(programVertexObjects[0])); Q_strncpyz(programFragmentObjects[0], "glsl/leifx_dither_fp.glsl", sizeof(programFragmentObjects[0])); tr.leiFXDitherProgram = RE_GLSL_RegisterProgram("leifx_dither", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); @@ -1519,33 +1452,58 @@ void R_GLSL_Init(void) Q_strncpyz(programFragmentObjects[0], "glsl/leifx_filter_fp.glsl", sizeof(programFragmentObjects[0])); tr.leiFXFilterProgram = RE_GLSL_RegisterProgram("leifx_filter", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - Q_strncpyz(programVertexObjects[0], "glsl/motionblur_accum_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/motionblur_accum_fp.glsl", sizeof(programFragmentObjects[0])); - tr.motionBlurProgram = RE_GLSL_RegisterProgram("motionblur_accum", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - Q_strncpyz(programVertexObjects[0], "glsl/motionblur_post_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/motionblur_post_fp.glsl", sizeof(programFragmentObjects[0])); - tr.motionBlurPostProgram = RE_GLSL_RegisterProgram("motionblur_post", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - Q_strncpyz(programVertexObjects[0], "glsl/brightness_vp.glsl", sizeof(programVertexObjects[0])); Q_strncpyz(programFragmentObjects[0], "glsl/brightness_fp.glsl", sizeof(programFragmentObjects[0])); - tr.BrightnessProgram = RE_GLSL_RegisterProgram("brightness", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); + if (!(tr.BrightnessProgram = RE_GLSL_RegisterProgram("brightness", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1))) + { + // load it through this code + ri.Printf( PRINT_ALL, "----- Trying to load Brightness Shader internally!!! \n" ); - Q_strncpyz(programVertexObjects[0], "glsl/crt_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/crt_fp.glsl", sizeof(programFragmentObjects[0])); - tr.CRTProgram = RE_GLSL_RegisterProgram("crt", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); + const GLchar *brightnessfp = \ + "#version 120 \n" + "uniform sampler2D u_Texture0; \n" + "varying vec2 texture_coordinate;\n" + "uniform float u_CC_Overbright; \n" + "uniform float u_CC_Gamma; \n" + "void main()\n" + "{\n" + "gl_FragColor = texture2D(u_Texture0, texture_coordinate); \n" + "vec3 color;\n" + "vec3 colord;\n" + "int coloredr;\n" + "int coloredg;\n" + "int coloredb;\n" + "color.r = 1;\n" + "color.g = 1;\n" + "color.b = 1;\n" + "int yeh = 0;\n" + "float ohyes;\n" + "// Overbrights\n" + "gl_FragColor *= (u_CC_Overbright + 1);\n" + "// Gamma Correction\n" + "float gamma = u_CC_Gamma;\n" + "gl_FragColor.r = pow(gl_FragColor.r, 1.0 / gamma);\n" + "gl_FragColor.g = pow(gl_FragColor.g, 1.0 / gamma);\n" + "gl_FragColor.b = pow(gl_FragColor.b, 1.0 / gamma);\n" + "}\n"; - Q_strncpyz(programVertexObjects[0], "glsl/ntsc_encode_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/ntsc_encode_fp.glsl", sizeof(programFragmentObjects[0])); - tr.NTSCEncodeProgram = RE_GLSL_RegisterProgram("ntsc_encode", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); + const GLchar *brightnessvp = \ + "varying vec2 texture_coordinate;\n" + "varying vec2 texture_coordinate2;\n" + "varying vec2 texture_coordinate3;\n" + "varying vec2 texture_coordinate4;\n" + "varying vec2 texture_coordinate5;\n" + "varying float scale;\n" + "uniform float u_CC_Overbright;\n" + "uniform float u_CC_Gamma;\n" + "void main()\n" + "{\n" + "gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n" + "texture_coordinate = vec2(gl_MultiTexCoord0); \n" + "}\n"; - Q_strncpyz(programVertexObjects[0], "glsl/ntsc_decode_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/ntsc_decode_fp.glsl", sizeof(programFragmentObjects[0])); - tr.NTSCDecodeProgram = RE_GLSL_RegisterProgram("ntsc_decode", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); - - Q_strncpyz(programVertexObjects[0], "glsl/ntsc_bleed_vp.glsl", sizeof(programVertexObjects[0])); - Q_strncpyz(programFragmentObjects[0], "glsl/ntsc_bleed_fp.glsl", sizeof(programFragmentObjects[0])); - tr.NTSCBleedProgram = RE_GLSL_RegisterProgram("ntsc_bleed", (const char *)programVertexObjects, 1, (const char *)programFragmentObjects, 1); + tr.BrightnessProgram = RE_GLSL_RegisterProgramRaw("brightnessInternal", (const char *)brightnessvp, 1, (const char *)brightnessfp, 1); + } if (strcmp( (const char *)r_postprocess->string, "none" )) { sprintf(p,"glsl/%s_vp.glsl",r_postprocess->string); @@ -1621,7 +1579,6 @@ void R_Init( void ) R_BloomInit(); R_PostprocessingInit(); R_AltBrightnessInit(); // leilei - alternate brightness - R_WaterInit(); // leilei - water test max_polys = r_maxpolys->integer; if (max_polys < MAX_POLYS) max_polys = MAX_POLYS; diff --git a/code/renderer_oa/tr_local.h b/code/renderer_oa/tr_local.h index 20bb4bc0..d524c1e6 100644 --- a/code/renderer_oa/tr_local.h +++ b/code/renderer_oa/tr_local.h @@ -86,8 +86,6 @@ typedef struct { vec3_t axis[3]; // orientation in world vec3_t viewOrigin; // viewParms->or.origin in local coordinates float modelMatrix[16]; - vec3_t viewOriginOld; // leilei - motionBlur - vec3_t viewOriginOlder; // leilei - motionBlur } orientationr_t; //=============================================================================== @@ -187,6 +185,7 @@ typedef enum { CGEN_FOG, // standard fog CGEN_CONST, // fixed color CGEN_VERTEX_LIT, // leilei - tess.vertexColors * tr.identityLight * ambientlight*directlight + CGEN_MATERIAL, // leilei - material system CGEN_LIGHTING_DIFFUSE_SPECULAR // leilei - LIGHTING_DIFFUSE, capped by specular exponent } colorGen_t; @@ -196,8 +195,6 @@ typedef enum { TCGEN_LIGHTMAP, TCGEN_TEXTURE, TCGEN_ENVIRONMENT_MAPPED, - TCGEN_ENVIRONMENT_CELSHADE_MAPPED, - TCGEN_ENVIRONMENT_CELSHADE_LEILEI, // leilei - cel hack TCGEN_ENVIRONMENT_MAPPED_WATER, // leilei - fake water reflection TCGEN_EYE_LEFT, // eyes TCGEN_EYE_RIGHT, // eyes @@ -265,6 +262,17 @@ typedef enum { TMOD_ENTITY_TRANSLATE } texMod_t; +// leilei - rgbMod - color modulations +typedef enum { + CMOD_BAD, + CMOD_GLOW, + CMOD_LIGHTING, + CMOD_NORMALIZETOALPHA, + CMOD_NORMALIZETOALPHAFAST, + CMOD_UVCOL, + CMOD_OPAQUE +} colorMod_t; + #define MAX_SHADER_DEFORMS 3 typedef struct { deform_t deformation; // vertex coordinate modification type @@ -308,7 +316,7 @@ typedef struct { } texModInfo_t; -#define MAX_IMAGE_ANIMATIONS 8 +#define MAX_IMAGE_ANIMATIONS 16 // leilei - was 8 typedef struct { image_t *image[MAX_IMAGE_ANIMATIONS]; @@ -355,12 +363,22 @@ typedef struct { int isGLSL; int isBlend; // leilei - for leifx - qboolean isLeiShade; // leilei - for the automatic shader qhandle_t program; int imgWidth; int imgHeight; //leilei for glsl shaders + colorMod_t rgbMod; // leilei - rgbMod + int rgbModCol; + int rgbModMode; + + int matAmb; // leilei - material ambience + int matDif; // leilei - material diffuse + int matSpec; // leilei - material specular + int matEmis; // leilei - material emissive + int matHard; // leilei - material specular hardness + int matAlpha; // leilei - material alpha + } shaderStage_t; struct shaderCommands_s; @@ -858,7 +876,7 @@ typedef struct { unsigned v_FogColor; GLint u_Greyscale; - int v_Greyscale; + int v_Greyscale; GLint u_IdentityLight; float v_IdentityLight; @@ -908,22 +926,6 @@ typedef struct { GLint u_ActualScreenSizeX; GLint u_ActualScreenSizeY; -// leilei - motion blur vars - - GLfloat u_MotionBlurX;// OBSOLETE - GLfloat u_MotionBlurY;// OBSOLETE - - GLint u_ViewMotion;// OBSOLETE - vec3_t v_ViewMotion;// OBSOLETE - - GLint u_mpass1; // 1-5 - GLint u_mpass2; // 6-10 - GLint u_mpass3; // 11-15 - GLint u_mpass4; // 16-20 - - GLint u_mpasses; // How many passes of Motion do we have anyhow? - - // leilei - 'compatibility' with ruby shader vars (HACK HACK HACK) GLint rubyInputSize; @@ -1098,17 +1100,11 @@ typedef struct { qboolean doneBloom; // done bloom this frame qboolean donepostproc; // done postprocess this frame qboolean doneleifx; // leilei - done leifxing this frame - qboolean doneanime; // leilei - done animeing this frame qboolean doneAltBrightness; // leilei - done alternate brightness this frame - qboolean doneFilm; // leilei - done film filtering this frame qboolean doneSun; // leilei - done drawing a sun qboolean doneSunFlare; // leilei - done drawing a sun flare - qboolean donemblur; // leilei - done motionblur this frame qboolean donewater; // leilei - done water this frame - qboolean donetv; // leilei - tv this frame - qboolean doneraa; // leilei - done aa'ing this frame - qboolean donentsc; // leilei - done ntsc'ing this frame - qboolean donepalette; // leilei - done animeing this frame + qboolean donepalette; // leilei - done paletting this frame qboolean doneSurfaces; // done any 3d surfaces already qboolean doneParticles; // done any particle movement qboolean doneFlareTests; // leilei - done testing flares @@ -1167,16 +1163,7 @@ typedef struct { qhandle_t leiFXDitherProgram; // leilei qhandle_t leiFXGammaProgram; // leilei qhandle_t leiFXFilterProgram; // leilei - qhandle_t animeProgram; // leilei - qhandle_t animeFilmProgram; // leilei - qhandle_t motionBlurProgram; // leilei - qhandle_t motionBlurPostProgram; // leilei qhandle_t BrightnessProgram; // leilei - qhandle_t CRTProgram; // leilei - qhandle_t NTSCEncodeProgram; // leilei - qhandle_t NTSCDecodeProgram; // leilei - qhandle_t NTSCBleedProgram; // leilei - qhandle_t paletteProgram; // leilei int numPrograms; glslProgram_t *programs[MAX_PROGRAMS]; @@ -1362,8 +1349,6 @@ extern cvar_t *r_skipBackEnd; extern cvar_t *r_anaglyphMode; -extern cvar_t *r_greyscale; - extern cvar_t *r_monolightmaps; extern cvar_t *r_ignoreGLErrors; @@ -1395,31 +1380,13 @@ extern cvar_t *r_flaresDlightFade; extern cvar_t *r_flaresDlightOpacity; extern cvar_t *r_flaresDlightScale; -extern cvar_t *r_flaresMotionBlur; -//extern cvar_t *r_flaresSurfradii; - extern cvar_t *r_alternateBrightness; // leilei - alternate brightness -extern cvar_t *r_parseStageSimple; // Leilei - handling textures into alphas extern cvar_t *r_leifx; // Leilei - leifx nostalgia filter -extern cvar_t *r_modelshader; // Leilei - new model shading +extern cvar_t *r_shadeMethod; // Leilei - new model shading methods -extern cvar_t *r_ntsc; // Leilei - ntsc - -extern cvar_t *r_tvMode; // Leilei - tv faking mode -extern cvar_t *r_tvModeForceAspect; // Leilei - retain aspect of the tv's mode -extern cvar_t *r_tvFilter; // Leilei - filter to use - - -extern cvar_t *r_retroAA; // Leilei - old console anti aliasing - extern cvar_t *r_suggestiveThemes; // Leilei - mature content -extern cvar_t *r_motionblur; // Leilei - motionblur -extern cvar_t *r_motionblur_fps; // Leilei - motionblur framerated - -extern cvar_t *r_anime; // Leilei - anime filter -extern cvar_t *r_palletize; // Leilei - anime filter extern cvar_t *r_leidebug; // Leilei - debug only! extern cvar_t *r_leidebugeye; // Leilei - debug only! extern cvar_t *r_particles; // Leilei - particles! @@ -1428,14 +1395,15 @@ extern cvar_t *r_iconmip; // leilei - icon mip - picmip for 2d icons extern cvar_t *r_iconBits; // leilei - icon color depth for 2d icons extern cvar_t *r_lightmapBits; // leilei - lightmap color depth - -extern cvar_t *r_texdump; // leilei - texture dumping +extern cvar_t *r_lightmapColorNorm; // leilei - lightmap color normalize extern cvar_t *r_detailTextureScale; // leilei - scale tweak the detail textures, 0 doesn't tweak at all. extern cvar_t *r_detailTextureLayers; // leilei - add in more smaller detail texture layers, expensive! extern cvar_t *r_textureDither; // leilei - apply dithering for lower texture bits +extern cvar_t *r_skytess; // leilei - adjusts the subdivisions of the sky (max 8, min 1) + //==================================================================== void R_SwapBuffers( int ); @@ -1919,14 +1887,6 @@ static ID_INLINE void R_GLSL_SetUniform_u_zFar(glslProgram_t *program, GLfloat v qglUniform1fARB(program->u_zFar, value); } -static ID_INLINE void R_GLSL_SetUniform_u_MotionBlurX(glslProgram_t *program, GLfloat value) { - qglUniform1fARB(program->u_MotionBlurX, value); -} - -static ID_INLINE void R_GLSL_SetUniform_u_MotionBlurY(glslProgram_t *program, GLfloat value) { - qglUniform1fARB(program->u_MotionBlurY, value); -} - static ID_INLINE void R_GLSL_SetUniform_u_CC_Brightness(glslProgram_t *program, GLfloat value) { qglUniform1fARB(program->u_CC_Brightness, value); @@ -1953,10 +1913,6 @@ static ID_INLINE void R_GLSL_SetUniform_u_CC_Overbright(glslProgram_t *program, } -static ID_INLINE void R_GLSL_SetUniform_u_mpasses(glslProgram_t *program, GLint value) { - qglUniform1iARB(program->u_mpasses, value); -} - static ID_INLINE void R_GLSL_SetUniform_u_ActualScreenSizeX(glslProgram_t *program, GLint value) { qglUniform1iARB(program->u_ActualScreenSizeX, value); } @@ -1992,15 +1948,9 @@ static ID_INLINE void R_GLSL_SetUniform_rubyOutputSize(glslProgram_t *program, c // qglUniform3fARB(program->rubyOutputSize, value, valub, 1.0); } - - -static ID_INLINE void R_GLSL_SetUniform_Mpass1(glslProgram_t *program, GLint value) {qglUniform1iARB(program->u_mpass1, value);} -static ID_INLINE void R_GLSL_SetUniform_Mpass2(glslProgram_t *program, GLint value) {qglUniform1iARB(program->u_mpass2, value);} -static ID_INLINE void R_GLSL_SetUniform_Mpass3(glslProgram_t *program, GLint value) {qglUniform1iARB(program->u_mpass3, value);} -static ID_INLINE void R_GLSL_SetUniform_Mpass4(glslProgram_t *program, GLint value) {qglUniform1iARB(program->u_mpass4, value);} - void R_GLSL_Init(void); qhandle_t RE_GLSL_RegisterProgram(const char *name, const char *programVertexObjects, int numVertexObjects, const char *programFragmentObjects, int numFragmentObjects); +qhandle_t RE_GLSL_RegisterProgramRaw(const char *name, const char *programVertexObjects, int numVertexObjects, const char *programFragmentObjects, int numFragmentObjects); void R_GLSL_UseProgram(qhandle_t index); void RB_GLSL_StageIteratorGeneric(void); void RB_GLSL_StageIteratorVertexLitTexture(void); @@ -2154,13 +2104,10 @@ void R_TransformClipToWindow( const vec4_t clip, const viewParms_t *view, vec4_t void RB_DeformTessGeometry( void ); void RB_CalcEnvironmentTexCoords( float *dstTexCoords ); -void RB_CalcCelTexCoords( float *dstTexCoords ); // leilei - cel hack -void RB_CalcEnvironmentTexCoordsJO( float *dstTexCoords ); // leilei -void RB_CalcEnvironmentTexCoordsR( float *dstTexCoords ); // leilei +void RB_CalcEnvironmentTexCoordsEx( float *st, int xx, int yy, int mode ); // leilei - extra envmapping + void RB_CalcEyes( float *st, qboolean theothereye); // leilei - eyes -void RB_CalcEnvironmentCelShadeTexCoords( float *dstTexCoords ); -void RB_CalcEnvironmentTexCoordsNew( float *dstTexCoords ); -void RB_CalcEnvironmentTexCoordsHW(void); + void RB_CalcFogTexCoords( float *dstTexCoords ); void RB_CalcScrollTexCoords( const float scroll[2], float *dstTexCoords ); void RB_CalcRotateTexCoords( float rotSpeed, float *dstTexCoords ); @@ -2175,19 +2122,18 @@ void RB_CalcWaveColor( const waveForm_t *wf, unsigned char *dstColors ); void RB_CalcAlphaFromEntity( unsigned char *dstColors ); void RB_CalcAlphaFromOneMinusEntity( unsigned char *dstColors ); void RB_CalcStretchTexCoords( const waveForm_t *wf, float *texCoords ); -void RB_CalcLightscaleTexCoords( float *texCoords ); void RB_CalcAtlasTexCoords( const atlas_t *at, float *st ); void RB_CalcColorFromEntity( unsigned char *dstColors ); void RB_CalcColorFromOneMinusEntity( unsigned char *dstColors ); void RB_CalcSpecularAlpha( unsigned char *alphas ); void RB_CalcSpecularAlphaNew( unsigned char *alphas ); +void RB_CalcGlowBlend( unsigned char *colors, int glowcol, int fx ); // leilei - rgbMod +void RB_CalcUVColor( unsigned char *colors, int glowcol, int fx ); // leilei - rgbMod +void RB_CalcNormalizeToAlpha( unsigned char *colors); // leilei - rgbMod void RB_CalcDiffuseColor( unsigned char *colors ); -void RB_CalcUniformColor( unsigned char *colors ); -void RB_CalcDynamicColor( unsigned char *colors ); -void RB_CalcDiffuseColor_Specular( unsigned char *colors ); // leilei - specular hack -void RB_CalcFlatAmbient( unsigned char *colors ); // leilei - cel hack -void RB_CalcFlatDirect( unsigned char *colors ); // leilei - cel hack -void RB_CalcNormal( unsigned char *colors ); // leilei - normal hack +void RB_CalcMaterials( unsigned char *colors, int ambient, int diffuse, int specular, int emissive, int spechard, int alpha ); // leilei - materials + +void RB_CalcVertLights( unsigned char *colors ); // leilei - dynamic vertex lights /* ============================================================= @@ -2347,12 +2293,7 @@ void RE_TakeVideoFrame( int width, int height, //Bloom Stuff void R_BloomInit( void ); -void R_WaterInit( void ); void R_BloomScreen( void ); -void R_WaterScreen( void ); -void R_AnimeScreen( void ); -void R_NTSCScreen( void ); -void R_PaletteScreen( void ); // Postprocessing void R_PostprocessScreen( void ); void R_PostprocessingInit(void); @@ -2360,14 +2301,10 @@ void R_PostprocessingInit(void); // leilei void R_BrightScreen( void ); void R_AltBrightnessInit( void ); -void R_FilmScreen( void ); // leilei - film effect extern int softwaremode; extern int leifxmode; extern int voodootype; // 0 - none 1 - Voodoo Graphics 2 - Voodoo2, 3 - Voodoo Banshee/3, 4 - Voodoo4/5 -void RB_UpdateMotionBlur (void); -void R_MotionBlur_BackupScreen(int which); - void R_AddParticles (void); void R_RenderParticles (void); void R_ClearParticles (void); diff --git a/code/renderer_oa/tr_mesh.c b/code/renderer_oa/tr_mesh.c index d0be29bc..4b63b110 100644 --- a/code/renderer_oa/tr_mesh.c +++ b/code/renderer_oa/tr_mesh.c @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" -static float ProjectRadius( float r, vec3_t location ) +float ProjectRadius( float r, vec3_t location ) { float pr; float dist; diff --git a/code/renderer_oa/tr_scene.c b/code/renderer_oa/tr_scene.c index b05578ca..fa1773e1 100644 --- a/code/renderer_oa/tr_scene.c +++ b/code/renderer_oa/tr_scene.c @@ -245,7 +245,21 @@ void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, floa if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) { return; } + dl = &backEndData->dlights[r_numdlights++]; + + // leilei - r_monolightmaps also desaturate vertex dynamic lights + float ml = r_monolightmaps->value; // sanitize + if (ml>1) ml=1; if (ml<0) ml=0; + + if( ml ) + { + float saturated = (r * 0.22126) + (g * 0.7152) + (b * 0.0722); + r = saturated + (r - saturated) * ( 1-ml ); + g = saturated + (g - saturated) * ( 1-ml ); + b = saturated + (b - saturated) * ( 1-ml ); + } + VectorCopy (org, dl->origin); dl->radius = intensity; dl->color[0] = r; @@ -361,7 +375,7 @@ void RE_RenderScene( const refdef_t *fd ) { // turn off dynamic lighting globally by clearing all the // dlights if it needs to be disabled or if vertex lighting is enabled if ( r_dynamiclight->integer == 0 || - r_vertexLight->integer == 1 || + // r_vertexLight->integer == 1 || // leilei - commented this out, as we can now do dynamic lights with vertex light glConfig.hardwareType == GLHW_PERMEDIA2 ) { tr.refdef.num_dlights = 0; } diff --git a/code/renderer_oa/tr_shade.c b/code/renderer_oa/tr_shade.c index c09cceed..88d6f0bd 100644 --- a/code/renderer_oa/tr_shade.c +++ b/code/renderer_oa/tr_shade.c @@ -502,31 +502,6 @@ static void ProjectDlightTexture_altivec( void ) { origin2 = dl->transformed[2]; radius = dl->radius; scale = 1.0f / radius; - - if(r_greyscale->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_monolightmaps->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_greyscale->value) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); - floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); - floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); - } - else { floatColor[0] = dl->color[0] * 255.0f; floatColor[1] = dl->color[1] * 255.0f; @@ -673,35 +648,9 @@ static void ProjectDlightTexture_scalar( void ) { radius = dl->radius; scale = 1.0f / radius; - if(r_greyscale->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_monolightmaps->integer) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = floatColor[1] = floatColor[2] = luminance; - } - else if(r_greyscale->value) - { - float luminance; - - luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; - floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); - floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); - floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); - } - else - { - floatColor[0] = dl->color[0] * 255.0f; - floatColor[1] = dl->color[1] * 255.0f; - floatColor[2] = dl->color[2] * 255.0f; - } + 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; @@ -807,6 +756,7 @@ static void ProjectDlightTexture( void ) { return; } #endif + if ( !r_vertexLight->integer ) ProjectDlightTexture_scalar(); } @@ -875,49 +825,19 @@ static void ComputeColors( shaderStage_t *pStage ) Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); break; case CGEN_LIGHTING_DIFFUSE: - if (r_shownormals->integer > 1 || (pStage->isLeiShade)){ - RB_CalcNormal( ( unsigned char * ) tess.svars.colors ); // leilei - debug normals, or use the normals as a color for a lighting shader - break; - } RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); - if(r_monolightmaps->integer) - { - int scale; - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } - } break; case CGEN_LIGHTING_UNIFORM: - RB_CalcUniformColor( ( unsigned char * ) tess.svars.colors ); - break; - case CGEN_LIGHTING_DYNAMIC: - RB_CalcDynamicColor( ( unsigned char * ) tess.svars.colors ); + RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); break; case CGEN_LIGHTING_FLAT_AMBIENT: - RB_CalcFlatAmbient( ( unsigned char * ) tess.svars.colors ); - if(r_monolightmaps->integer) - { - int scale; - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } + for ( i = 0; i < tess.numVertexes; i++ ) { + *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; } break; case CGEN_LIGHTING_FLAT_DIRECT: - RB_CalcFlatDirect( ( unsigned char * ) tess.svars.colors ); - if(r_monolightmaps->integer) - { - int scale; - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } + for ( i = 0; i < tess.numVertexes; i++ ) { + *(int *)tess.svars.colors[i] = *(int *)pStage->constantColor; } break; case CGEN_EXACT_VERTEX: @@ -944,35 +864,10 @@ static void ComputeColors( shaderStage_t *pStage ) } } break; - case CGEN_VERTEX_LIT: // leilei - mixing vertex colors with lighting through a glorious light hack - { // should only be used for entity models, not map assets! - vec3_t dcolor, acolor; // to save the color from actual light - vec3_t vcolor; - int y; - - - // Backup our colors - VectorCopy( backEnd.currentEntity->ambientLight, acolor ); - VectorCopy( backEnd.currentEntity->directedLight, dcolor ); - VectorCopy( backEnd.currentEntity->e.shaderRGBA, vcolor ); - - // Make our vertex color take over - - for(y=0;y<3;y++){ - backEnd.currentEntity->ambientLight[y] *= (vcolor[y] / 255); - - if (backEnd.currentEntity->ambientLight[y] < 1) backEnd.currentEntity->ambientLight[y] = 1; // black!!! - if (backEnd.currentEntity->ambientLight[y] > 255) backEnd.currentEntity->ambientLight[y] = 255; // white!!!!! - // backEnd.currentEntity->ambientLight[y] *= (vcolor[y] / 255); - // backEnd.currentEntity->directedLight[y] *= (vcolor[y] / 255); - } - - // run it through our favorite preferred lighting calculation functions - RB_CalcDiffuseColor( ( unsigned char * ) tess.svars.colors ); - - // Restore light color for any other stage that doesn't do it - VectorCopy( acolor, backEnd.currentEntity->ambientLight); - VectorCopy( dcolor, backEnd.currentEntity->directedLight); + case CGEN_VERTEX_LIT: // leilei - for world only + { + Com_Memcpy( tess.svars.colors, tess.vertexColors, tess.numVertexes * sizeof( tess.vertexColors[0] ) ); + RB_CalcVertLights( ( unsigned char * ) tess.svars.colors ); } break; case CGEN_ONE_MINUS_VERTEX: @@ -1015,59 +910,11 @@ static void ComputeColors( shaderStage_t *pStage ) case CGEN_ONE_MINUS_ENTITY: RB_CalcColorFromOneMinusEntity( ( unsigned char * ) tess.svars.colors ); break; - case CGEN_LIGHTING_DIFFUSE_SPECULAR: // leilei - specular hack - if (r_shownormals->integer > 1 || (pStage->isLeiShade)){ - RB_CalcNormal( ( unsigned char * ) tess.svars.colors ); // leilei - debug normals, or use the normals as a color for a lighting shader - break; - } - RB_CalcDiffuseColor_Specular( ( unsigned char * ) tess.svars.colors ); - if(r_monolightmaps->integer) - { - int scale; - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } - } + case CGEN_MATERIAL: + RB_CalcMaterials( ( unsigned char * ) tess.svars.colors, pStage->matAmb, pStage->matDif, pStage->matSpec, pStage->matEmis, pStage->matHard, pStage->matAlpha ); break; } - // leilei PowerVR Hack - - if (r_parseStageSimple->integer) - { - float scale; - vec3_t normme; - if ((pStage->isBlend == 1) || (pStage->isBlend == 3)){ // additive or subtracive - - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][3] = scale - tess.svars.colors[i][3]; - if (tess.svars.colors[i][3] > 255) tess.svars.colors[i][3] = 255; - - - normme[0] = tess.svars.colors[i][0]; - normme[1] = tess.svars.colors[i][1]; - normme[2] = tess.svars.colors[i][2]; - - // normme[0] *= (4 * tr.identityLight); - // normme[1] *= (4 * tr.identityLight); - // normme[2] *= (4 * tr.identityLight); - - - VectorNormalize(normme); - - - tess.svars.colors[i][0] = normme[0]*255; - tess.svars.colors[i][1] = normme[1]*255; - tess.svars.colors[i][2] = normme[2]*255; - } - } - - } - // // alphaGen // @@ -1153,6 +1000,34 @@ static void ComputeColors( shaderStage_t *pStage ) break; } + // + // rgbMod + // + switch ( pStage->rgbMod ) + { + case CMOD_GLOW: + RB_CalcGlowBlend( ( unsigned char * ) tess.svars.colors, pStage->rgbModCol, pStage->rgbModMode ); + break; + case CMOD_UVCOL: + RB_CalcUVColor( ( unsigned char * ) tess.svars.colors, pStage->rgbModCol, pStage->rgbModMode ); + break; + case CMOD_NORMALIZETOALPHA: + RB_CalcNormalizeToAlpha( ( unsigned char * ) tess.svars.colors ); + break; + case CMOD_NORMALIZETOALPHAFAST: // TODO: use first vert + RB_CalcNormalizeToAlpha( ( unsigned char * ) tess.svars.colors ); + break; + case CMOD_OPAQUE: + for ( i = 0; i < tess.numVertexes; i++ ) + tess.svars.colors[i][3] = 0xff; + break; + case CMOD_LIGHTING: + // TODO + break; + case CMOD_BAD: + return; + } + // // fog adjustment for colors to fade out as fog increases // @@ -1174,30 +1049,43 @@ static void ComputeColors( shaderStage_t *pStage ) } } - // 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 = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; - } - } - else if(r_greyscale->value) - { - float scale; - - for(i = 0; i < tess.numVertexes; i++) - { - scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); - tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value); - tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value); - tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value); - } - } } + +/* +=============== +ComputeUVColors +=============== +*/ +static void ComputeUVColors( shaderStage_t *pStage ) +{ + // + // rgbMod + // + switch ( pStage->rgbMod ) + { + case CMOD_GLOW: + // we do this elsewhere + break; + case CMOD_UVCOL: + RB_CalcUVColor( ( unsigned char * ) tess.svars.colors, pStage->rgbModCol, pStage->rgbModMode ); + break; + case CMOD_NORMALIZETOALPHA: + break; + case CMOD_NORMALIZETOALPHAFAST: // TODO: use first vert + break; + case CMOD_OPAQUE: + break; + case CMOD_LIGHTING: + break; + case CMOD_BAD: + return; + } + + +} + + /* =============== ComputeTexCoords @@ -1243,13 +1131,7 @@ static void ComputeTexCoords( shaderStage_t *pStage ) { RB_CalcEnvironmentTexCoords( ( float * ) tess.svars.texcoords[b] ); break; case TCGEN_ENVIRONMENT_MAPPED_WATER: - RB_CalcEnvironmentTexCoordsJO( ( float * ) tess.svars.texcoords[b] ); - break; - case TCGEN_ENVIRONMENT_CELSHADE_MAPPED: - RB_CalcEnvironmentCelShadeTexCoords( ( float * ) tess.svars.texcoords[b] ); - break; - case TCGEN_ENVIRONMENT_CELSHADE_LEILEI: - RB_CalcCelTexCoords( ( float * ) tess.svars.texcoords[b] ); + RB_CalcEnvironmentTexCoordsEx( ( float * ) tess.svars.texcoords[b], 0, 1, 1 ); break; case TCGEN_EYE_LEFT: RB_CalcEyes( ( float * ) tess.svars.texcoords[b], 1); @@ -1301,10 +1183,6 @@ static void ComputeTexCoords( shaderStage_t *pStage ) { ( float * ) tess.svars.texcoords[b] ); break; - case TMOD_LIGHTSCALE: - RB_CalcLightscaleTexCoords( ( float * ) tess.svars.texcoords[b] ); - break; - case TMOD_TRANSFORM: RB_CalcTransformTexCoords( &pStage->bundle[b].texMods[tm], ( float * ) tess.svars.texcoords[b] ); @@ -1373,10 +1251,6 @@ void GLSL_Feeder(shaderStage_t *pStage, shaderCommands_t *input) if (program->u_FogColor > -1 && tess.fogNum) R_GLSL_SetUniform_FogColor(program, (tr.world->fogs + tess.fogNum)->colorInt); - /* greyscale */ - if (program->u_Greyscale > -1) - R_GLSL_SetUniform_Greyscale(program, r_greyscale->integer); - /* identity light */ if (program->u_IdentityLight > -1) R_GLSL_SetUniform_IdentityLight(program, tr.identityLight); @@ -1468,11 +1342,6 @@ void GLSL_Feeder(shaderStage_t *pStage, shaderCommands_t *input) R_BindAnimatedImage(&pStage->bundle[7]); } - if (program->u_mpass1 > -1 && pStage->bundle[1].image[0]) { GL_SelectTexture(11); qglEnable(GL_TEXTURE_2D); R_BindAnimatedImage(&pStage->bundle[11]);} - if (program->u_mpass2 > -1 && pStage->bundle[1].image[0]) { GL_SelectTexture(12); qglEnable(GL_TEXTURE_2D); R_BindAnimatedImage(&pStage->bundle[12]);} - if (program->u_mpass3 > -1 && pStage->bundle[1].image[0]) { GL_SelectTexture(13); qglEnable(GL_TEXTURE_2D); R_BindAnimatedImage(&pStage->bundle[13]);} - if (program->u_mpass4 > -1 && pStage->bundle[1].image[0]) { GL_SelectTexture(14); qglEnable(GL_TEXTURE_2D); R_BindAnimatedImage(&pStage->bundle[14]);} - /* time */ if (program->u_Time > -1) R_GLSL_SetUniform_Time(program, input->shaderTime); @@ -1488,11 +1357,6 @@ void GLSL_Clean(void) { glslProgram_t *program; program = tr.programs[glState.currentProgram]; - - if (program->u_mpass1 > -1) { GL_SelectTexture(11); qglDisable(GL_TEXTURE_2D); } - if (program->u_mpass2 > -1) { GL_SelectTexture(12); qglDisable(GL_TEXTURE_2D); } - if (program->u_mpass3 > -1) { GL_SelectTexture(13); qglDisable(GL_TEXTURE_2D); } - if (program->u_mpass4 > -1) { GL_SelectTexture(14); qglDisable(GL_TEXTURE_2D); } /* disable texture unit 7 */ if (program->u_Texture7 > -1) diff --git a/code/renderer_oa/tr_shade_calc.c b/code/renderer_oa/tr_shade_calc.c index 31236a56..7d3018fc 100644 --- a/code/renderer_oa/tr_shade_calc.c +++ b/code/renderer_oa/tr_shade_calc.c @@ -108,43 +108,6 @@ void RB_CalcStretchTexCoords( const waveForm_t *wf, float *st ) RB_CalcTransformTexCoords( &tmi, st ); } - -// leilei - this is for celshading -void RB_CalcLightscaleTexCoords(float *st ) -{ - float p; - texModInfo_t tmi; - float light = 1.0f; -#if 0 - vec3_t lightDir; - vec3_t ambientLight; - VectorCopy( backEnd.currentEntity->ambientLight, ambientLight ); - VectorCopy( backEnd.currentEntity->lightDir, lightDir ); -#endif - vec3_t directedLight; - VectorCopy( backEnd.currentEntity->directedLight, directedLight ); - //light = DotProduct (directedLight, lightDir); - light = ((directedLight[0] + directedLight[1] + directedLight[2]) * 0.333) / 255; - if (light > 1) - light = 1.0f; - - p = 1.0f - (light * 0.7f); - - tmi.matrix[0][0] = p; - tmi.matrix[1][0] = 0; - tmi.translate[0] = 0.5f - 0.5f * p; - - tmi.matrix[0][1] = 0; - tmi.matrix[1][1] = p; - tmi.translate[1] = 0.5f - 0.5f * p; - - RB_CalcTransformTexCoords( &tmi, st ); -} - - - - - /* ==================================================================== @@ -1082,194 +1045,125 @@ void RB_CalcEnvironmentTexCoordsNew( float *st ) /* -** RB_CalcEnvironmentTexCoordsHW +** RB_CalcEnvironmentTexCoordsEx + + leilei - extended environment texcoords (to replace redundancy), to: - Hardware-native cubemapping (or sphere mapping if the former is unsupported) + - specify which axis are used + - imitate raven behavior + - allow reflection from local lights (i.e. for celshading, or weapon glimmer) - adapted from this tremulous patch by Odin - - NOTE: THIS BREAKS OTHER TCMODS IN A STAGE + mode 1 = raven mode (including weapon shine). + note: this ISN'T from JediOutcast but rather clean-room experiments for VitaVoyager + mode 2 = weapon shine + mode 3 = all models shine + mode 4? = sun shine (water)? + mode 5 - view space (i.e. buffer reflections/refractions) */ -void RB_CalcEnvironmentTexCoordsHW() -{ - qglTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - qglTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - qglTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - qglEnable(GL_TEXTURE_GEN_S); - qglEnable(GL_TEXTURE_GEN_T); - qglEnable(GL_TEXTURE_GEN_R); -} - - -/* -** RB_CalcEnvironmentTexCoordsJO - from JediOutcast source -*/ -void RB_CalcEnvironmentTexCoordsJO( float *st ) +void RB_CalcEnvironmentTexCoordsEx( float *st, int xx, int yy, int mode ) { int i; float *v, *normal; - vec3_t viewer; + vec3_t viewer, reflected; float d; v = tess.xyz[0]; normal = tess.normal[0]; - if (backEnd.currentEntity && backEnd.currentEntity->e.renderfx&RF_FIRST_PERSON) //this is a view model so we must use world lights instead of vieworg + // clamp these + if (xx > 2) xx = 2; if (yy > 2) yy = 2; + if (xx < 0) xx = 0; if (yy < 0) yy = 0; + + if (mode == 1) // raven { - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) + if (backEnd.currentEntity->e.renderfx & RF_FIRST_PERSON) // Weapons { - d = DotProduct (normal, backEnd.currentEntity->lightDir); - st[0] = normal[0]*d - backEnd.currentEntity->lightDir[0]; - st[1] = normal[1]*d - backEnd.currentEntity->lightDir[1]; + for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) + { + VectorCopy (backEnd.currentEntity->lightDir, viewer); + VectorNormalizeFast (viewer); + + d = DotProduct (normal, viewer); + + reflected[xx] = normal[xx]*2*d - viewer[xx]; + reflected[yy] = normal[yy]*2*d - viewer[yy]; + + st[0] = reflected[xx] * 0.5; + st[1] = reflected[yy] * 0.5; + } + } + else // World + { + for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) + { + VectorSubtract (backEnd.or.viewOrigin, v, viewer); + VectorNormalizeFast (viewer); + + d = DotProduct (normal, viewer); + + reflected[xx] = normal[xx]*2*d - viewer[xx]; + reflected[yy] = normal[yy]*2*d - viewer[yy]; + + st[0] = reflected[xx] * 0.5; + st[1] = reflected[yy] * 0.5; + } + } + } + else if (mode == 5) // view space + { + { + for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) + { + vec3_t deflected; + vec4_t deflecteder; + VectorSubtract (backEnd.or.viewOrigin, v, viewer); + VectorNormalizeFast (viewer); + + + R_TransformModelToClip(v, backEnd.or.modelMatrix, backEnd.viewParms.projectionMatrix, deflected, deflecteder ); + + VectorNormalizeFast(deflecteder); + + st[0] = 0.5 + deflecteder[0] * 0.5; + st[1] = 0.5 + deflecteder[1] * 0.5; + } + } + } + + else + { + if ((backEnd.currentEntity->e.renderfx & RF_FIRST_PERSON && mode == 2) || ( ( backEnd.currentEntity != &tr.worldEntity ) && mode == 3)) // local light sine + { + for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) + { + VectorCopy (backEnd.currentEntity->lightDir, viewer); + VectorNormalizeFast (viewer); + + d = DotProduct (normal, viewer); + + reflected[xx] = normal[xx]*2*d - viewer[xx]; + reflected[yy] = normal[yy]*2*d - viewer[yy]; + + st[0] = 0.5 + reflected[xx] * 0.5; + st[1] = 0.5 - reflected[yy] * 0.5; + } } - } else { //the normal way for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) { VectorSubtract (backEnd.or.viewOrigin, v, viewer); VectorNormalizeFast (viewer); - + d = DotProduct (normal, viewer); - st[0] = normal[0]*d - 0.5*viewer[0]; - st[1] = normal[1]*d - 0.5*viewer[1]; + + reflected[xx] = normal[xx]*2*d - viewer[xx]; + reflected[yy] = normal[yy]*2*d - viewer[yy]; + + st[0] = 0.5 + reflected[xx] * 0.5; + st[1] = 0.5 - reflected[yy] * 0.5; } } } -/* -** RB_CalcEnvironmentTexCoordsR - Inpsired by Revolution, reflect from the sun light position instead -*/ - -void RB_CalcEnvironmentTexCoordsR( float *st ) -{ - int i; - float *v, *normal; - vec3_t viewer, reflected, sunned; - float d; - vec3_t sundy; - float size; - float dist; - vec3_t vec1, vec2; - - v = tess.xyz[0]; - normal = tess.normal[0]; - - dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3) - size = dist * 0.4; - - VectorScale( tr.sunDirection, dist, sundy); - PerpendicularVector( vec1, tr.sunDirection ); - CrossProduct( tr.sunDirection, vec1, vec2 ); - - VectorScale( vec1, size, vec1 ); - VectorScale( vec2, size, vec2 ); - - - v = tess.xyz[0]; - normal = tess.normal[0]; - - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) - { - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - VectorNormalizeFast (viewer); - - VectorSubtract (sundy, v, sunned); - VectorNormalizeFast (sunned); - - d = DotProduct (normal, viewer) + DotProduct (viewer, sunned); - - reflected[0] = normal[0]*2*d - viewer[0]; - reflected[1] = normal[1]*2*d - viewer[1]; - reflected[2] = normal[2]*2*d - viewer[2]; - - st[0] = 0.5 + reflected[1] * 0.5; - st[1] = 0.5 - reflected[2] * 0.5; - } -} - -/* -** RB_CalcCelTexCoords - Butchered from JediOutcast source, note that this is not the same method as ZEQ2. -*/ -void RB_CalcCelTexCoords( float *st ) -{ - int i; - float *v, *normal; - vec3_t viewer, reflected, lightdir, directedLight; - float d, l, p; - - - v = tess.xyz[0]; - normal = tess.normal[0]; - - VectorCopy(backEnd.currentEntity->lightDir, lightdir); - VectorCopy(backEnd.currentEntity->directedLight, directedLight); - float light = (directedLight[0] + directedLight[1] + directedLight[2] / 3); - p = 1.0f - (light / 255); - - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) - { - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - VectorNormalizeFast (viewer); - - d = DotProduct (normal, viewer); - - l = DotProduct (normal, backEnd.currentEntity->lightDir); - - if (d < 0)d = 0; - if (l < 0)l = 0; - - if (d < p)d = p; - if (l < p)l = p; - - reflected[0] = normal[0]*1*(d+l) - (viewer[0] + lightdir[0] ); - reflected[1] = normal[1]*1*(d+l) - (viewer[1] + lightdir[1] ); - reflected[2] = normal[2]*1*(d+l) - (viewer[2] + lightdir[2] ); - - st[0] = 0.5 + reflected[1] * 0.5; - st[1] = 0.5 - reflected[2] * 0.5; - - } -} - - - -/* -** RB_CalcEnvironmentCelShadeTexCoords -** -** RiO; celshade 1D environment map -*/ - - - - -void RB_CalcEnvironmentCelShadeTexCoords( float *st ) -{ - int i; - float *v, *normal; - vec3_t lightDir; - float d; - - normal = tess.normal[0]; - v = tess.xyz[0]; - - // Calculate only once -// VectorCopy( backEnd.currentEntity->lightDir, lightDir ); -// if ( backEnd.currentEntity == &tr.worldEntity ) -// VectorSubtract( lightOrigin, v, lightDir ); -// else - VectorCopy( backEnd.currentEntity->lightDir, lightDir ); - VectorNormalizeFast( lightDir ); - - for (i = 0 ; i < tess.numVertexes ; i++, v += 4, normal += 4, st += 2 ) { - d= DotProduct( normal, lightDir ); - - st[0] = 0.5 + d * 0.5; - st[1] = 0.5; - } -} - /* ** RB_CalcTurbulentTexCoords */ @@ -1577,11 +1471,209 @@ int i; } + + +/* +** RB_GlowBlend +** +** leilei - blends a specific color (specified in hex) +*/ + +static void RB_GlowBlend( unsigned char *colors, int glowcol, int fx ) +{ + int i; + float *v, *normal; + float incoming; + vec3_t lightDir; + vec3_t directedLight; + int numVertexes; + + directedLight[0] = (glowcol >> 16) & 0xFF; + directedLight[1] = (glowcol >> 8 ) & 0xFF; + directedLight[2] = glowcol & 0xFF; + + // if we don't have overbrights, we need to beef up the colors + if (tr.identityLight == 1){ + int f; + for (f=0;f<3;f++) + { + directedLight[f] *=2; + if (directedLight[f]>255)directedLight[f]=255; + } + } + + VectorCopy( backEnd.or.viewOrigin, lightDir ); + + v = tess.xyz[0]; + normal = tess.normal[0]; + VectorNormalizeFast( lightDir ); + + numVertexes = tess.numVertexes; + for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { + + if (fx == 1) + incoming = sin(i+(tess.shaderTime * 12)) * DotProduct (normal, lightDir); // fluctuate! + else if (fx == 2) + incoming = sin((tess.shaderTime * 12)) * DotProduct (normal, lightDir); // pulsate! + else if (fx == 3){ + incoming = DotProduct (normal, lightDir) * 4.0; + incoming = sin(incoming+tess.shaderTime * 16); // wave + } + else if (fx == 6) + { + float eh, off; + vec3_t the; + + eh = (v[0] + v[1] + v[2]) * 3; + off = sin(eh + tess.shaderTime * 5); + + VectorScale( normal, off, the); + + incoming = VectorNormalize(the); + if (colors[i*4+3] < 128) incoming = 0; + + // clamp + if (incoming > 1) incoming = 1; + if (incoming < 0) incoming = 0; + + // blend the new color over the current color + colors[i*4+0] = (colors[i*4+0] * (1-incoming)) + ((incoming) * directedLight[0]); + colors[i*4+1] = (colors[i*4+1] * (1-incoming)) + ((incoming) * directedLight[1]); + colors[i*4+2] = (colors[i*4+2] * (1-incoming)) + ((incoming) * directedLight[2]); + return; + } + else // generic glow + { + incoming = DotProduct (normal, lightDir) * 0.8f; + } + + // clamp + if (incoming > 1) incoming = 1; + if (incoming < 0) incoming = 0; + + // blend the new color over the current color + colors[i*4+0] = (colors[i*4+0] * (incoming)) + ((1-incoming) * directedLight[0]); + colors[i*4+1] = (colors[i*4+1] * (incoming)) + ((1-incoming) * directedLight[1]); + colors[i*4+2] = (colors[i*4+2] * (incoming)) + ((1-incoming) * directedLight[2]); + } +} + + + +/* +** RB_UVColor +** +** leilei - blends a specific color (specified in hex) +*/ + +static void RB_UVColor( unsigned char *colors, int glowcol, int fx ) +{ + int i; + float *v, *normal; + float incoming; + vec3_t lightDir; + vec3_t directedLight; + float *texc; + vec3_t col; + + int numVertexes; + vec3_t newcol; + + directedLight[0] = (glowcol >> 16) & 0xFF; + directedLight[1] = (glowcol >> 8 ) & 0xFF; + directedLight[2] = glowcol & 0xFF; + + + VectorCopy( backEnd.or.viewOrigin, lightDir ); + + v = tess.xyz[0]; + normal = tess.normal[0]; + texc = tess.texCoords[0]; + + numVertexes = tess.numVertexes; + for (i = 0 ; i < numVertexes ; i++, v += 4, texc+=2 ) { + int tf; + // For each mode, deal with fading for towards the edge of a uvmap + + incoming = 0; + if (fx == 0) // Off the top edge, set it to the color + { + if (texc[1] < 0.0f) incoming = 1; + } + if (fx == 1) // Fade it + { + if (v[4] < 0.0f) incoming = 255; + } + + for(tf=0 ; tf<3 ; tf++ ) + { + newcol[tf] = incoming; + + if (newcol[tf] > 255) newcol[tf] = 255; + if (newcol[tf] < 0) newcol[tf] = 0; + } + + // blend the new color over the current color + colors[i*4+0] = newcol[0]; + colors[i*4+1] = newcol[1]; + colors[i*4+2] = newcol[2]; + } +} + + + + /* ** RB_CalcDiffuseColor ** ** The basic vertex lighting calc */ + +// leilei - with some extra modes (flat, high, rim) + +// fastest possible path - but shouldn't be very bright. +static void RB_CalcDiffuseColor_flat( unsigned char *colors ) +{ + int i; + float *v, *normal; + trRefEntity_t *ent; + vec3_t ambientLight; + vec3_t directedLight; + int numVertexes; + ent = backEnd.currentEntity; + VectorCopy( ent->ambientLight, ambientLight ); + VectorCopy( ent->directedLight, directedLight ); + + v = tess.xyz[0]; + normal = tess.normal[0]; + numVertexes = tess.numVertexes; + + int r = ri.ftol(ambientLight[0] + directedLight[0]); + int g = ri.ftol(ambientLight[1] + directedLight[1]); + int b = ri.ftol(ambientLight[2] + directedLight[2]); + + r = (ambientLight[0] + r) / 2; + g = (ambientLight[1] + g) / 2; + b = (ambientLight[2] + b) / 2; + + if (r < ambientLight[0]) r = ambientLight[0]; + if (g < ambientLight[1]) g = ambientLight[1]; + if (b < ambientLight[2]) b = ambientLight[2]; + + if ( r > 255 ) r = 255; + if ( g > 255 ) g = 255; + if ( b > 255 ) b = 255; + + for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { + colors[i*4+0] = r; + colors[i*4+1] = g; + colors[i*4+2] = b; + colors[i*4+3] = 255; + } +} + + + #if idppc_altivec static void RB_CalcDiffuseColor_altivec( unsigned char *colors ) { @@ -1702,192 +1794,7 @@ static void RB_CalcDiffuseColor_scalar( unsigned char *colors ) } } -// leilei - reveal normals to GLSL for light processing. HACK HACK HACK HACK HACK HACK -void RB_CalcNormal( unsigned char *colors ) -{ - float *v; - float *normal = ( float * ) tess.normal; - vec3_t n, m; - int numVertexes; - - v = tess.xyz[0]; - //normal = tess.normal[0]; - - numVertexes = tess.numVertexes; - for (int i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - int y; - float mid; - for (y=0;y<3;y++){ - n[y] = normal[y]; - -// colors[i*4+y] = n[y]; - } - //VectorNormalize(n); - - mid = n[1] + n[2]; - if (mid < 0) mid *= -1; - - - // m[0] = 127 - (n[1]*128); - // m[1] = 127 - (n[2]*128); - // m[2] = 255 - (mid*128); - - m[0] = 127 + (n[0]*128); - m[1] = 127 + (n[1]*128); - m[2] = 127 + (n[2]*128); - - - - - colors[i*4+0] = m[0]; - colors[i*4+1] = m[1]; - colors[i*4+2] = m[2]; - colors[i*4+3] = 255; - } -} - - - -void RB_CalcDiffuseColor_Specular( unsigned char *colors ) -{ - int i, j; - float spec; - float *v, *normal; - float incoming; - trRefEntity_t *ent; - int ambientLightInt; - vec3_t ambientLight; - vec3_t lightDir; - vec3_t directedLight; - vec3_t specularLight; - int numVertexes; - int shadecap = 200; // was 127 - ent = backEnd.currentEntity; - ambientLightInt = ent->ambientLightInt; - VectorCopy( ent->ambientLight, ambientLight ); - VectorCopy( ent->directedLight, directedLight ); - - VectorCopy( ent->directedLight, specularLight ); - VectorAdd( ent->ambientLight, directedLight, directedLight ); - VectorCopy( ent->lightDir, lightDir ); - - // averaging colors test -/* - { - int rf; - for (rf=0;rf<3;rf++){ - //directedLight[rf] = ambientLight[rf] + directedLight[rf] / 2; - //ambientLight[rf] = pow((ambientLight[rf] / 255), (directedLight[rf] / 255)) * 255; - specularLight[rf] -= ambientLight[rf]; - ambientLight[rf] = ambientLight[rf] + ambientLight[rf] + (directedLight[rf] / 512); - - - //shadecap += directedLight[rf]; - if (specularLight[rf] < 0) specularLight[rf] = 0; - if (ambientLight[rf] > 255) ambientLight[rf] = 255; - - } - //shadecap /= 3; - - ambientLightInt *= 1.5; - - } -*/ - v = tess.xyz[0]; - normal = tess.normal[0]; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - incoming = DotProduct (normal, lightDir); - - if ( incoming <= 0 ) { - *(int *)&colors[i*4] = ambientLightInt; - continue; - } - - - // Specular - - { - float ilength; - vec3_t viewer, reflected; - - VectorCopy( backEnd.currentEntity->lightDir, lightDir ); - VectorNormalizeFast( lightDir ); - - // calculate the specular color - float d = DotProduct (normal, lightDir); - - // we don't optimize for the d < 0 case since this tends to - // cause visual artifacts such as faceted "snapping" - reflected[0] = normal[0]*2*d - lightDir[0]; - reflected[1] = normal[1]*2*d - lightDir[1]; - reflected[2] = normal[2]*2*d - lightDir[2]; - - VectorSubtract (backEnd.or.viewOrigin, v, viewer); - ilength = Q_rsqrt( DotProduct( viewer, viewer ) ); - float l = DotProduct (reflected, viewer); - l *= ilength; - - if (l < 0) { - spec = 0; - } else { - l = l*l; - l = l*l; - spec = l * 2.2f; - if (spec > 1) spec = 1; - } - // specularLight[0] += spec; - // specularLight[1] += spec; - // specularLight[2] += spec; - - // if (specularLight[0] < shadecap) specularLight[0] = 0; - // if (specularLight[1] < shadecap) specularLight[1] = 0; - // if (specularLight[2] < shadecap) specularLight[2] = 0; - - // if (specularLight[0]) specularLight[0] = 255; - // if (specularLight[1]) specularLight[1] = 255; - // if (specularLight[2]) specularLight[2] = 255; - } - - j = ri.ftol(ambientLight[0] + incoming * directedLight[0]); - if ( j > shadecap ) { - j = shadecap; - j += ri.ftol(spec * specularLight[0]); - } - - // j += specularLight[0]; - if ( j > 255) j = 255; - colors[i*4+0] = j; - - j = ri.ftol(ambientLight[1] + incoming * directedLight[1]); - if ( j > shadecap ) { - j = shadecap; - j += ri.ftol(spec * specularLight[1]); - } - - // j += specularLight[1]; - if ( j > 255) j = 255; - - - colors[i*4+1] = j; - - j = ri.ftol(ambientLight[2] + incoming * directedLight[2]); - if ( j > shadecap ) { - j = shadecap; - j += ri.ftol(spec * specularLight[2]); - } - - // j += specularLight[2]; - if ( j > 255) j = 255; - colors[i*4+2] = j; - - colors[i*4+3] = 255; - } -} - - - +extern float ProjectRadius( float r, vec3_t location ); void RB_CalcDiffuseColor( unsigned char *colors ) { #if idppc_altivec @@ -1899,174 +1806,402 @@ void RB_CalcDiffuseColor( unsigned char *colors ) #endif - // leilei - reduced it to just this, r_shadeMode deprecated. :( - RB_CalcDiffuseColor_scalar( colors ); - - -} - -/* -** RB_CalcUniformColor -** -** RiO; Uniform vertex color lighting for cel shading -*/ -void RB_CalcUniformColor( unsigned char *colors ) -{ - - int i; - trRefEntity_t *ent; - vec3_t ambientLight; - //vec3_t directedLight; - vec4_t uniformLight; - int numVertexes; - float normalize; - - ent = backEnd.currentEntity; - - VectorCopy( ent->ambientLight, ambientLight ); - //VectorCopy( ent->directedLight, directedLight ); - - VectorAdd( ambientLight, ambientLight/*directedLight*/, uniformLight ); - - normalize = NormalizeColor( uniformLight, uniformLight ); - if ( normalize > 255 ) normalize = 255; - VectorScale( uniformLight, normalize, uniformLight ); - uniformLight[3] = 255; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++ ) { - colors[i*4+0] = uniformLight[0]; - colors[i*4+1] = uniformLight[1]; - colors[i*4+2] = uniformLight[2]; - colors[i*4+3] = uniformLight[3]; + if (r_shadeMethod->integer == -1) // Fastest + { + RB_CalcDiffuseColor_flat( colors ); } + else if (r_shadeMethod->integer == 2) // mimic UE1 style + { + RB_CalcMaterials( colors, 0xFFFFFF, 0x000000, 0xFFFFFF, 0x000000, 128, 255 ); + } + else if (r_shadeMethod->integer == 3) // have a little both diffuse and specular for a balanced look + { + RB_CalcMaterials( colors, 0xFFFFFF, 0x808080, 0x808080, 0x000000, 128, 255 ); + } + else if ((r_shadeMethod->integer > 150) && (r_shadeMethod->integer < 667)) // values in a certain range is an adaptive LOD selection of -1, 0 and 3 + { + float projectedRadius, fsh, shadescale, radius; + trRefEntity_t *ent = backEnd.currentEntity; + fsh = 1; + radius = 1; + if ( ( projectedRadius = ProjectRadius( radius, ent->e.origin ) ) != 0 ) + { + shadescale = r_shadeMethod->value*-0.2; + if (shadescale > 666) shadescale = 666; + fsh = 1.0f - projectedRadius * shadescale; + } + if (fsh > 5) + RB_CalcMaterials( colors, 0xFFFFFF, 0x808080, 0x808080, 0x000000, 128, 255 ); + else if (fsh > 2.5) + RB_CalcDiffuseColor_scalar( colors ); + else + RB_CalcDiffuseColor_flat( colors ); + + } + else // standard idtech3 shading + { + RB_CalcDiffuseColor_scalar( colors ); + } + } -/* -** RB_CalcDynamicColor -** -** MDave; Vertex color dynamic lighting for cel shading -*/ -void RB_CalcDynamicColor( unsigned char *colors ) + + +void RB_CalcGlowBlend( unsigned char *colors, int glowcol, int fx ) +{ + RB_GlowBlend( colors, glowcol, fx ); +} + +void RB_CalcUVColor( unsigned char *colors, int glowcol, int fx ) +{ + RB_UVColor( colors, glowcol, fx ); +} + + +// normalize colors but alpha has the intensity of the colors. +void RB_CalcNormalizeToAlpha( unsigned char *colors) { int i; - trRefEntity_t *ent; - vec4_t dynamic; - int numVertexes; - float normalize; - - ent = backEnd.currentEntity; - - VectorCopy( ent->dynamicLight, dynamic ); - - normalize = NormalizeColor( dynamic, dynamic ); - if ( normalize > 255 ) normalize = 255; - VectorScale( dynamic, normalize, dynamic ); - dynamic[3] = 255; - - numVertexes = tess.numVertexes; - for (i = 0 ; i < numVertexes ; i++ ) { - colors[i*4+0] = dynamic[0]; - colors[i*4+1] = dynamic[1]; - colors[i*4+2] = dynamic[2]; - colors[i*4+3] = dynamic[3]; - } -} - - -// leilei celsperiment - - -void RB_CalcFlatAmbient( unsigned char *colors ) -{ - int i, j; float *v, *normal; - trRefEntity_t *ent; - vec3_t ambientLight; int numVertexes; - ent = backEnd.currentEntity; - VectorCopy( ent->ambientLight, ambientLight ); + + v = tess.xyz[0]; + normal = tess.normal[0]; // do we even need this + + numVertexes = tess.numVertexes; + for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { + + colors[i*4+3] = LUMA(colors[i*4+0], colors[i*4+1], colors[i*4+2]); + // leilei - boost it up a little more to fight pvr1's subtractive modulation + //colors[i*4+3] = pow(colors[i*4+3]/255,0.7f)*255; + { + int max; + + max = colors[i*4+0] > colors[i*4+1] ? colors[i*4+0] : colors[i*4+1]; + max = max > colors[i*4+2] ? max : colors[i*4+2]; + max += 1; + colors[i*4+0] = colors[i*4+0] * 255 / max; + colors[i*4+1] = colors[i*4+1] * 255 / max; + colors[i*4+2] = colors[i*4+2] * 255 / max; + + } + } +} + + + +/* +** RB_VertLightsPerVert +** +** leilei - for maps, try to light up vertex lighting with dynamic lights +*/ + + +static void RB_VertLightsPerVert( unsigned char *colors ) +{ + int i, f; + float *v, *normal; + int numVertexes; + + vec3_t cl; + vec3_t cv; v = tess.xyz[0]; normal = tess.normal[0]; numVertexes = tess.numVertexes; for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - j = ri.ftol(ambientLight[0]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+0] = j; + // get the world colors + cl[0] = colors[i*4+0]; + cl[1] = colors[i*4+1]; + cl[2] = colors[i*4+2]; - j = ri.ftol(ambientLight[1]); - if ( j > 255 ) { - j = 255; - } - colors[i*4+1] = j; - j = ri.ftol(ambientLight[2]); - if ( j > 255 ) { - j = 255; + if(r_dynamiclight->integer) + { + for (f=0 ; fcolor[0]; g = l->color[1]; b = l->color[2]; + + if (l->radius >= 1) // if light is good, mark the map + { + // calc the light against the world verts + VectorSubtract( l->origin, v, cv ); + float power = 2048 * ( l->radius ); + float d = VectorNormalize( cv ); + power = power / ( d * d ); + if (power < 0) power = 0; + + // add the color of the light + cl[0] += (r * power); + cl[1] += (g * power); + cl[2] += (b * power); + + // clamp stuff + // normalize by color instead of saturating to white + if ( ( (int)cl[0] | (int)cl[1] | (int)cl[2] ) > 255 ) { + int max; + + max = cl[0] > cl[1] ? cl[0] : cl[1]; + max = max > cl[2] ? max : cl[2]; + cl[0] = cl[0] * 255 / max; + cl[1] = cl[1] * 255 / max; + cl[2] = cl[2] * 255 / max; + } + if (cl[0] < 0) cl[0] = 0; + if (cl[1] < 0) cl[1] = 0; + if (cl[2] < 0) cl[2] = 0; + } + } } - colors[i*4+2] = j; - colors[i*4+3] = 255; + // give the world our new modulated color + colors[i*4+0] = cl[0]; + colors[i*4+1] = cl[1]; + colors[i*4+2] = cl[2]; + } } -void RB_CalcFlatDirect( unsigned char *colors ) +void RB_CalcVertLights( unsigned char *colors ) { - int i, j; + RB_VertLightsPerVert( colors ); +} + +#define MAXFRESLIGHTS 512 + +/* +** RB_CalcMaterialColor +** +** leilei - for more control on diffuse/ambient/emiss/specular colors rather than diffuse only. Possibly could use some SIMD magic here +*/ + +static void RB_CalcMaterialColor( unsigned char *colors, int maxl, int ambient, int diffuse, int specular, int emissive, int spechard, int alpha ) +{ + int i, j, l; float *v, *normal; trRefEntity_t *ent; vec3_t ambientLight; - vec3_t directedLight; - int numVertexes; + int numVertexes; + vec3_t lorigin; + + vec3_t matAmb, matDif, matSpec, matEmis; + float matHard = spechard / 128.0f; + int specenabled = 0; + + + if (spechard == 128) + matHard = 1; + + if (specular) + specenabled = 1; + + // Parse material colors + + matAmb[0] = ((ambient >> 16) & 0xFF); + matAmb[1] = ((ambient >> 8 ) & 0xFF); + matAmb[2] = (ambient & 0xFF); + + matDif[0] = ((diffuse >> 16) & 0xFF); + matDif[1] = ((diffuse >> 8 ) & 0xFF); + matDif[2] = (diffuse & 0xFF); + + matSpec[0] = ((specular >> 16) & 0xFF); + matSpec[1] = ((specular >> 8 ) & 0xFF); + matSpec[2] = (specular & 0xFF); + + matEmis[0] = (emissive >> 16) & 0xFF; + matEmis[1] = (emissive >> 8 ) & 0xFF; + matEmis[2] = emissive & 0xFF; + + VectorNormalize( matAmb ); + VectorNormalize( matDif ); + VectorNormalize( matSpec ); + VectorNormalize( matEmis ); + + // Overbright clamp + + matEmis[0] *= tr.identityLight; + matEmis[1] *= tr.identityLight; + matEmis[2] *= tr.identityLight; + + // setup ent + ent = backEnd.currentEntity; + + if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) + VectorCopy( ent->e.lightingOrigin, lorigin ); + else + VectorCopy( ent->e.origin, lorigin ); + + VectorCopy( ent->ambientLight, ambientLight ); - VectorCopy( ent->directedLight, directedLight ); + + int liteOn[maxl]; + vec3_t liteOrg[maxl]; + vec3_t liteCol[maxl]; + int active = 1; + + if (maxl > MAXFRESLIGHTS) maxl = MAXFRESLIGHTS; + + // first light is always the world + liteOn[0] = 1; + VectorCopy( ent->directedLight, liteCol[0] ); + VectorCopy( ent->lightDir, liteOrg[0] ); + + ambientLight[0] *= matAmb[0]*2; + ambientLight[1] *= matAmb[1]*2; + ambientLight[2] *= matAmb[2]*2; + + if (maxl>1) + { + // add dynamic lights + { + dlight_t *l; - directedLight[0] -= ambientLight[0]; - directedLight[1] -= ambientLight[1]; - directedLight[2] -= ambientLight[2]; + for (i=0 ; imaxl) + continue; + l = &backEnd.refdef.dlights[i]; + + VectorCopy( l->color, liteCol[active] ); + + VectorSubtract( l->origin, lorigin, liteOrg[active] ); + + // attenuation + float d = VectorNormalize( liteOrg[active] ); + float power = 16 * ( l->radius ); + power = power / ( d * d ); + if (power < 0) power = 0; + if (power > 1) power = 1; // needed to prevent powerup light overflow, as quad/flagcarriers players should not glow themselves + + // transform + liteOrg[active][0] = DotProduct( liteOrg[active], ent->e.axis[0] ); + liteOrg[active][1] = DotProduct( liteOrg[active], ent->e.axis[1] ); + liteOrg[active][2] = DotProduct( liteOrg[active], ent->e.axis[2] ); + + liteCol[active][0] *= (255 * power); + liteCol[active][1] *= (255 * power); + liteCol[active][2] *= (255 * power); + + liteOn[active] = 1; + active++; + + } + } + } + + + // Set up our model v = tess.xyz[0]; normal = tess.normal[0]; numVertexes = tess.numVertexes; + + for (i = 0 ; i < numVertexes ; i++, v += 4, normal += 4) { - j = ri.ftol(directedLight[0]); + vec3_t difs; + vec3_t specs; + + // clear + difs[0] = difs[1] = difs[2] = 0; + specs[0] = specs[1] = specs[2] = 0; + + // HACK - Fix the world light + VectorCopy( ent->lightDir, liteOrg[0] ); + + // go through lights and add them + for (l=0;l 1) { + b = 1; + } + } + + specs[0] += b * liteCol[l][0]; + specs[1] += b * liteCol[l][1]; + specs[2] += b * liteCol[l][2]; + } + + if (c<0) c=0; + if (c>255) c=255; + if (liteOn[l] != 2){ + difs[0] += c * liteCol[l][0]; + difs[1] += c * liteCol[l][1]; + difs[2] += c * liteCol[l][2]; + } + + } + + // Add Ambient and CLAMP + j = ri.ftol(ambientLight[0] + (difs[0] * matDif[0]) + (specs[0] * matSpec[0])); if ( j > 255 ) { j = 255; } colors[i*4+0] = j; - j = ri.ftol(directedLight[1]); + j = ri.ftol(ambientLight[1] + (difs[1] * matDif[1]) + (specs[1] * matSpec[1])); if ( j > 255 ) { j = 255; } colors[i*4+1] = j; - j = ri.ftol(directedLight[2]); + j = ri.ftol(ambientLight[2] + (difs[2] * matDif[2]) + (specs[2] * matSpec[2])); if ( j > 255 ) { j = 255; } colors[i*4+2] = j; - colors[i*4+3] = 255; + + colors[i*4+3] = alpha; } } +void RB_CalcMaterials( unsigned char *colors, int ambient, int diffuse, int specular, int emissive, int spechard, int alpha ) +{ + // TODO: Low detail materials + RB_CalcMaterialColor( colors, 1, ambient, diffuse, specular, emissive, spechard, alpha ); - - - - +} diff --git a/code/renderer_oa/tr_shader.c b/code/renderer_oa/tr_shader.c index df509228..a279e1eb 100644 --- a/code/renderer_oa/tr_shader.c +++ b/code/renderer_oa/tr_shader.c @@ -134,9 +134,6 @@ static glslProgram_t *R_GLSL_AllocProgram(void) { program->u_ScreenToNextPixelX = -1; program->u_ScreenToNextPixelY = -1; program->u_zFar = -1; - program->u_MotionBlurX = -1; - program->u_MotionBlurY = -1; - program->u_mpasses = -1; program->u_CC_Brightness = -1; program->u_CC_Gamma = -1; program->u_CC_Overbright = -1; @@ -194,8 +191,6 @@ static void R_GLSL_ParseProgram(glslProgram_t *program, char *_text) { program->u_ActualScreenSizeX = qglGetUniformLocationARB(program->program, "u_ActualScreenSizeX"); } else if (!Q_stricmp(token, "u_ActualScreenSizeY;")) { program->u_ActualScreenSizeY = qglGetUniformLocationARB(program->program, "u_ActualScreenSizeY"); - } else if (!Q_stricmp(token, "u_mpasses;")) { - program->u_mpasses = qglGetUniformLocationARB(program->program, "u_mpasses"); } else { ri.Printf(PRINT_WARNING, "WARNING: uniform int %s unrecognized in program %s\n", token, program->name); } @@ -213,10 +208,6 @@ static void R_GLSL_ParseProgram(glslProgram_t *program, char *_text) { program->u_ScreenToNextPixelY = qglGetUniformLocationARB(program->program, "u_ScreenToNextPixelY"); } else if (!Q_stricmp(token, "u_zFar;")) { program->u_zFar = qglGetUniformLocationARB(program->program, "u_zFar"); - } else if (!Q_stricmp(token, "u_MotionBlurX;")) { - program->u_MotionBlurX = qglGetUniformLocationARB(program->program, "u_MotionBlurX"); - } else if (!Q_stricmp(token, "u_MotionBlurY;")) { - program->u_MotionBlurY = qglGetUniformLocationARB(program->program, "u_MotionBlurY"); } else if (!Q_stricmp(token, "u_CC_Brightness;")) { program->u_CC_Brightness = qglGetUniformLocationARB(program->program, "u_CC_Brightness"); } else if (!Q_stricmp(token, "u_CC_Overbright;")) { @@ -465,6 +456,137 @@ static qboolean R_GLSL_LoadProgram(glslProgram_t *program, const char *name, con #endif } +static qboolean R_GLSL_LoadProgramRaw(glslProgram_t *program, const char *name, const char *programVertexObjects, int numVertexObjects, const char *programFragmentObjects, int numFragmentObjects) { +#ifdef GLSL_BACKEND + GLcharARB *buffer_vp[MAX_PROGRAM_OBJECTS]; + GLcharARB *buffer_fp[MAX_PROGRAM_OBJECTS]; + GLcharARB *buffer; + GLhandleARB shader_vp; + GLhandleARB shader_fp; + GLint status; + char *str; + int size = 0; + int i; + + + /* create program */ + program->program = qglCreateProgramObjectARB(); + + /* vertex program */ + for (i = 0, str = (const char *)programVertexObjects; i < numVertexObjects; i++, str += MAX_QPATH) { + buffer_vp[i] = str; + size += sizeof(str)*32; + if (!buffer_vp[i]) { + ri.Printf( PRINT_WARNING, "Couldn't load %s", str); + return qfalse; + } + + /* compile vertex shader */ + shader_vp = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); + qglShaderSourceARB(shader_vp, 1, (const GLcharARB **)&buffer_vp, NULL); + qglCompileShaderARB(shader_vp); + + /* check for errors in vertex shader */ + qglGetObjectParameterivARB(shader_vp, GL_OBJECT_COMPILE_STATUS_ARB, &status); + if (!status) { + int length; + char *msg; + + /* print glsl error message */ + qglGetObjectParameterivARB(shader_vp, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + msg = ri.Hunk_AllocateTempMemory(length); + qglGetInfoLogARB(shader_vp, length, &length, msg); + ri.Printf(PRINT_ALL, "Error:\n%s\n", msg); + ri.Hunk_FreeTempMemory(msg); + + /* exit */ + ri.Printf( PRINT_WARNING, "Couldn't compile vertex shader for program %s", name); + return qfalse; + } + + /* attach vertex shader to program */ + qglAttachObjectARB(program->program, shader_vp); + qglDeleteObjectARB(shader_vp); + } + + /* fragment program */ + for (i = 0, str = (const char *)programFragmentObjects; i < numFragmentObjects; i++, str += MAX_QPATH) { + buffer_fp[i] = str; + size += sizeof(str)*32; + if (!buffer_fp[i]) { + ri.Printf( PRINT_WARNING, "Couldn't load %s", str); + return qfalse; + } + + /* compile fragment shader */ + shader_fp = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); + qglShaderSourceARB(shader_fp, 1, (const GLcharARB **)&buffer_fp[i], NULL); + qglCompileShaderARB(shader_fp); + + /* check for errors in fragment shader */ + qglGetObjectParameterivARB(shader_fp, GL_OBJECT_COMPILE_STATUS_ARB, &status); + if (!status) { + int length; + char *msg; + + /* print glsl error message */ + + qglGetObjectParameterivARB(shader_fp, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + msg = ri.Hunk_AllocateTempMemory(length); + qglGetInfoLogARB(shader_fp, length, &length, msg); + ri.Printf(PRINT_ALL, "Error:\n%s\n", msg); + ri.Hunk_FreeTempMemory(msg); + ri.Printf(PRINT_DEVELOPER, "oops\n"); + /* exit */ + ri.Printf( PRINT_WARNING, "Couldn't compile fragment shader for program %s", name); + return qfalse; + } + + /* attach fragment shader to program */ + qglAttachObjectARB(program->program, shader_fp); + qglDeleteObjectARB(shader_fp); + } + + /* link complete program */ + qglLinkProgramARB(program->program); + /* check for linking errors */ + qglGetObjectParameterivARB(program->program, GL_OBJECT_LINK_STATUS_ARB, &status); + if (!status) { + int length; + char *msg; + /* print glsl error message */ + qglGetObjectParameterivARB(program->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length); + msg = ri.Hunk_AllocateTempMemory(length); + qglGetInfoLogARB(program->program, length, &length, msg); + ri.Printf(PRINT_ALL, "Error:\n%s\n", msg); + ri.Hunk_FreeTempMemory(msg); + + /* exit */ + ri.Printf( PRINT_WARNING, "Couldn't link shaders for program %s", name); + return qfalse; + } + /* build single large program file for parsing */ + buffer = ri.Hunk_AllocateTempMemory(++size); + + Q_strncpyz(buffer, buffer_vp[0], size); + + for (i = 1; i < numVertexObjects; i++) + strncat(buffer, buffer_vp[i], size); + for (i = 0; i < numFragmentObjects; i++) + strncat(buffer, buffer_fp[i], size); + /* get uniform locations */ + qglUseProgramObjectARB(program->program); + R_GLSL_ParseProgram(program, buffer); + qglUseProgramObjectARB(0); + /* clean up */ + ri.Hunk_FreeTempMemory(buffer); + + return qtrue; +#endif +} + + + /* * RE_GLSL_RegisterProgram * Loads in a program of given name @@ -523,6 +645,65 @@ qhandle_t RE_GLSL_RegisterProgram(const char *name, const char *programVertexObj } +/* + * RE_GLSL_RegisterProgram + * Loads in a program of given name + */ +qhandle_t RE_GLSL_RegisterProgramRaw(const char *name, const char *programVertexObjects, int numVertexObjects, const char *programFragmentObjects, int numFragmentObjects) { +#ifdef GLSL_BACKEND + glslProgram_t *program; + qhandle_t hProgram; + + if (!vertexShaders) + return 0; + + if (!name || !name[0]) { + ri.Printf(PRINT_ALL, "RE_GLSL_RegisterProgram: NULL name\n"); + return 0; + } + + if (strlen(name) >= MAX_QPATH) { + Com_Printf("Program name exceeds MAX_QPATH\n"); + return 0; + } + + /* search the currently loaded programs */ + for (hProgram = 0; hProgram < tr.numPrograms; hProgram++) { + program = tr.programs[hProgram]; + if (!strcmp(program->name, name)) { + if (!program->valid) + return 0; + + return hProgram; + } + } + + /* allocate a new glslProgram_t */ + if ((program = R_GLSL_AllocProgram()) == NULL) { + ri.Printf(PRINT_WARNING, "RE_GLSL_RegisterProgram: R_GLSL_AllocProgram() failed for '%s'\n", name); + return 0; + } + + /* only set the name after the program has successfully loaded */ + Q_strncpyz(program->name, name, sizeof(program->name)); + + R_IssuePendingRenderCommands(); + + /* load the files */ + if (!R_GLSL_LoadProgramRaw(program, name, (const char*)programVertexObjects, numVertexObjects, (const char*)programFragmentObjects, numFragmentObjects)) { + qglDeleteObjectARB(program->program); + program->valid = qfalse; + //vertexShaders=0; //If program in error disable the glsl feature altogether + return 0; + } + + program->valid = qtrue; + return program->index; +#endif +} + + + void R_RemapShader(const char *shaderName, const char *newShaderName, const char *timeOffset) { char strippedName[MAX_QPATH]; int hash; @@ -993,7 +1174,6 @@ static void ParseTexMod( char *_text, shaderStage_t *stage ) return; } tmi->atlas.width = atof( token ); - ri.Printf( PRINT_WARNING, "shader '%s' has width %f\n", shader.name, tmi->atlas.width ); token = COM_ParseExt( text, qfalse ); if ( token[0] == 0 ) @@ -1006,13 +1186,6 @@ static void ParseTexMod( char *_text, shaderStage_t *stage ) tmi->type = TMOD_ATLAS; } - else if ( !Q_stricmp( token, "lightscale" ) ) - { - token = COM_ParseExt( text, qfalse ); - - tmi->type = TMOD_LIGHTSCALE; - } - // // transform // @@ -1096,14 +1269,56 @@ static void ParseTexMod( char *_text, shaderStage_t *stage ) } + +/* +============== +ParseNum / ParseHex +============== +*/ +int ShParseHex (const char *hex) +{ + const char *str; + int num; + + num = 0; + str = hex; + + while (*str) + { + num <<= 4; + if (*str >= '0' && *str <= '9') + num += *str-'0'; + else if (*str >= 'a' && *str <= 'f') + num += 10 + *str-'a'; + else if (*str >= 'A' && *str <= 'F') + num += 10 + *str-'A'; + else + return 0; + str++; + } + + return num; +} + + +static int ShParseNum (const char *str) +{ + if (str[0] == '$') + return ShParseHex (str+1); + if (str[0] == '0' && str[1] == 'x') + return ShParseHex (str+2); + return atol (str); +} + + + /* =================== ParseStage =================== */ -qboolean ParseStageSimple( shaderStage_t *stage, char **text ); -extern cvar_t *r_parseStageSimple; // Leilei - for debugging PVR only! + static qboolean ParseStage( shaderStage_t *stage, char **text ) { @@ -1118,13 +1333,6 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) qboolean stageMipmaps = !shader.noMipMaps; - // leilei - switch to simple for simple cards - if (r_parseStageSimple->integer){ - - return ParseStageSimple(stage, text); - } - - stage->active = qtrue; Com_Memset(programName, 0, sizeof(programName)); @@ -1367,7 +1575,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) // // map3 // - else if ( !Q_stricmp( token, "map3" ) || (!Q_stricmp( token, "normalmap" ) && r_modelshader->integer)) + else if ( !Q_stricmp( token, "map3" ) || (!Q_stricmp( token, "normalmap" ))) { token = COM_ParseExt( text, qfalse ); if ( !token[0] ) @@ -1415,7 +1623,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) // // map4 // - else if ( !Q_stricmp( token, "map4" ) || (!Q_stricmp( token, "specmap" ) && r_modelshader->integer)) + else if ( !Q_stricmp( token, "map4" ) || (!Q_stricmp( token, "specmap" ))) { token = COM_ParseExt( text, qfalse ); if ( !token[0] ) @@ -1462,7 +1670,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) // // map5 // - else if ( !Q_stricmp( token, "map5" ) || (!Q_stricmp( token, "shadeballmap" ) && r_modelshader->integer)) + else if ( !Q_stricmp( token, "map5" ) || (!Q_stricmp( token, "shadeballmap" ))) { token = COM_ParseExt( text, qfalse ); if ( !token[0] ) @@ -2636,47 +2844,65 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) { stage->rgbGen = CGEN_EXACT_VERTEX; } - else if ( !Q_stricmp( token, "vertexLighting" ) ) // leilei - vertex WITH a lighting pass after - { - stage->rgbGen = CGEN_VERTEX_LIT; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "vertexLighting2" ) ) // leilei - second vertex color - { - stage->rgbGen = CGEN_VERTEX_LIT; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } else if ( !Q_stricmp( token, "lightingDiffuse" ) ) { stage->rgbGen = CGEN_LIGHTING_DIFFUSE; } - else if ( !Q_stricmp( token, "lightingUniform" ) ) - { - stage->rgbGen = CGEN_LIGHTING_UNIFORM; - } - else if ( !Q_stricmp( token, "lightingDynamic" ) ) - { - stage->rgbGen = CGEN_LIGHTING_DYNAMIC; - } - else if ( !Q_stricmp( token, "flatAmbient" ) ) - { - stage->rgbGen = CGEN_LIGHTING_FLAT_AMBIENT; - } - else if ( !Q_stricmp( token, "flatDirect" ) ) - { - stage->rgbGen = CGEN_LIGHTING_FLAT_DIRECT; - } else if ( !Q_stricmp( token, "oneMinusVertex" ) ) { stage->rgbGen = CGEN_ONE_MINUS_VERTEX; } - else if ( !Q_stricmp( token, "lightingSpecularDiffuse" ) ) // leilei - deprecated + else if ( !Q_stricmp( token, "material" ) ) // leilei - material system { - stage->rgbGen = CGEN_LIGHTING_DIFFUSE; + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing ambient color in shader '%s', using white\n", shader.name ); + stage->matAmb = 0xFFFFFF; + } + else + stage->matAmb = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing diffuse color in shader '%s', using gray\n", shader.name ); + stage->matSpec = 0xEEEEEE; + } + else + stage->matDif = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing specular color for material in shader '%s', using none\n", shader.name ); + stage->matSpec = 0x000000; + } + else + stage->matSpec = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing emissive color for material in shader '%s', using none\n", shader.name ); + stage->matEmis = 0x000000; + } + else + stage->matEmis = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing specular hardness for material in shader '%s', using none\n", shader.name ); + stage->matHard = 0; + } + else + stage->matHard = atoi( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing alpha for material in shader '%s', using opaque\n", shader.name ); + stage->matAlpha = 255; + } + else + stage->matAlpha = atoi( token ); + + stage->rgbGen = CGEN_MATERIAL; } else { @@ -2752,6 +2978,83 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } } // + // rgbMod + // + else if ( !Q_stricmp( token, "rgbMod" ) ) + { + token = COM_ParseExt( text, qfalse ); + if ( token[0] == 0 ) + { + ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbMod in shader '%s'\n", shader.name ); + continue; + } + if ( !Q_stricmp( token, "glow" ) ) + { + // TODO: Parse "entity" and "vertex" for their colors, for railguns and maps + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing hex color in shader '%s'\n", shader.name ); + return qfalse; + } + stage->rgbModCol = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + stage->rgbModMode = 0; + stage->rgbMod = CMOD_GLOW; + return qtrue; + } + stage->rgbModMode = atoi( token ); + + stage->rgbMod = CMOD_GLOW; + } + if ( !Q_stricmp( token, "uvcol" ) ) + { + // Parse color + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + ri.Printf( PRINT_WARNING, "WARNING: missing hex color in shader '%s'\n", shader.name ); + return qfalse; + } + stage->rgbModCol = ShParseNum( token ); + + token = COM_ParseExt( text, qfalse ); + if ( !token[0] ) { + stage->rgbModMode = 0; + stage->rgbMod = CMOD_UVCOL; + return qtrue; + } + stage->rgbModMode = atoi( token ); + + stage->rgbMod = CMOD_UVCOL; + } + if ( !Q_stricmp( token, "normtoalpha" ) ) + { + // normalize colors, but average color prior is alpha. + stage->rgbMod = CMOD_NORMALIZETOALPHA; + } + if ( !Q_stricmp( token, "normtoalphafast" ) ) + { + // normalize and use the first vert's color on whole surface, but average color prior is alpha. + stage->rgbMod = CMOD_NORMALIZETOALPHAFAST; + } + if ( !Q_stricmp( token, "lighting" ) ) + { + // modulate a standard diffuse light on top of existing vertex colors + stage->rgbMod = CMOD_LIGHTING; + } + if ( !Q_stricmp( token, "opaque" ) ) + { + // modulate a standard diffuse light on top of existing vertex colors + stage->rgbMod = CMOD_OPAQUE; + } + else + { + ri.Printf( PRINT_WARNING, "WARNING: unknown rgbMod parameter '%s' in shader '%s'\n", token, shader.name ); + continue; + } + } + // // tcGen // else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) ) @@ -2769,11 +3072,11 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } else if ( !Q_stricmp( token, "cel" ) ) { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_CELSHADE_MAPPED; + stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; } else if ( !Q_stricmp( token, "celshading" ) ) // leilei - my technique is different { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_CELSHADE_LEILEI; + stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; } else if ( !Q_stricmp( token, "eyeleft" ) ) // leilei - eye tracking { @@ -2897,851 +3200,9 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } -/* -=================== -ParseStageSimple - - -leilei - the purpose of this is to load textures after processing their blending properties, - so we can approximate effects on incapable hardware such as Matrox Mystique, S3 ViRGE, - PowerVR PCX2, software rendering... - A lot of things are stripped out (like GLSL and multitexture stuff) -=================== -*/ - extern int hackoperation; extern int ismaptexture; int surfaceflagsy; -qboolean ParseStageSimple( shaderStage_t *stage, char **text ) -{ - char *token; - char programName[MAX_QPATH]; - char programVertexObjects[MAX_PROGRAM_OBJECTS][MAX_QPATH]; - char programFragmentObjects[MAX_PROGRAM_OBJECTS][MAX_QPATH]; - char imageName[MAX_QPATH]; // for loading later - char imageNameAnim0[MAX_QPATH]; - char imageNameAnim1[MAX_QPATH]; - char imageNameAnim2[MAX_QPATH]; - char imageNameAnim3[MAX_QPATH]; - char imageNameAnim4[MAX_QPATH]; - char imageNameAnim5[MAX_QPATH]; - char imageNameAnim6[MAX_QPATH]; - char imageNameAnim7[MAX_QPATH]; - char imageNameAnim8[MAX_QPATH]; - imgType_t itype = IMGTYPE_COLORALPHA; - imgFlags_t iflags = IMGFLAG_NONE; - int numVertexObjects = 0; - int numFragmentObjects = 0; - int loadlater = 0; - int depthMaskBits = GLS_DEPTHMASK_TRUE, blendSrcBits = 0, blendDstBits = 0, atestBits = 0, depthFuncBits = 0; - qboolean depthMaskExplicit = qfalse; - - qboolean stageMipmaps = !shader.noMipMaps; - stage->active = qtrue; - Com_Memset(programName, 0, sizeof(programName)); - - - hackoperation = 2; // reset the hackop - - while ( 1 ) - { - - - - //stage->isBlend = 0; - token = COM_ParseExt( text, qtrue ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: no matching '}' found\n" ); - return qfalse; - } - - if ( token[0] == '}' ) - { -#ifdef GLSL_TEXTURES - if (programName[0]) { - if (!Q_stricmp(programName, "skip")) { - stage->program = tr.skipProgram; - } else { - if (!numVertexObjects) { - ri.Printf(PRINT_WARNING, "WARNING: no 'vertexProgram' specified for 'program %s' in shader '%s'\n", programName, shader.name); - return qfalse; - } - - if (!numFragmentObjects) { - ri.Printf(PRINT_WARNING, "WARNING: no 'fragmentProgram' specified for 'program %s' in shader '%s'\n", programName, shader.name); - return qfalse; - } - - stage->isGLSL=0; - stage->program = RE_GLSL_RegisterProgram(programName, (const char *)programVertexObjects, numVertexObjects, (const char *)programFragmentObjects, numFragmentObjects); - if (!stage->program) { - ri.Printf(PRINT_WARNING, "WARNING: RE_GLSL_RegisterProgram failed for 'program %s' in shader '%s'\n", programName, shader.name); - //return qfalse; - } - else - stage->isGLSL=1; - } - } else if (numVertexObjects) { - ri.Printf(PRINT_WARNING, "WARNING: no 'program' specified for 'vertexProgram' in shader '%s'\n", shader.name); - return qfalse; - } else if (numFragmentObjects) { - ri.Printf(PRINT_WARNING, "WARNING: no 'program' specified for 'fragmentProgram' in shader '%s'\n", shader.name); - return qfalse; - } -#endif - break; - } - // - // program - // - else if (!Q_stricmp(token, "program")) { - token = COM_ParseExt(text, qfalse); - - if (!vertexShaders) - continue; - - if (!token[0]) { - ri.Printf(PRINT_WARNING, "WARNING: missing parameter for 'program' keyword in shader '%s'\n", shader.name); - return qfalse; - } - - Q_strncpyz(programName, token, sizeof(programName)); - } - // - // vertexProgram .... - // - else if (!Q_stricmp(token, "vertexProgram")) { - token = COM_ParseExt(text, qfalse); - - if (!vertexShaders) { - while (token[0]) - token = COM_ParseExt(text, qfalse); - - continue; - } - - if (!token[0]) { - ri.Printf(PRINT_WARNING, "WARNING: missing parameter(s) for 'vertexProgram' keyword in shader '%s'\n", shader.name); - return qfalse; - } - - // parse up to MAX_PROGRAM_OBJECTS files - for(;;) { - if (numVertexObjects < MAX_PROGRAM_OBJECTS) { - Q_strncpyz(programVertexObjects[numVertexObjects], token, sizeof(programVertexObjects[numVertexObjects])); - numVertexObjects++; - } else { - ri.Printf(PRINT_WARNING, "WARNING: Too many parameters for 'vertexProgram' keyword in shader '%s'\n", shader.name); - return qfalse; - } - - token = COM_ParseExt(text, qfalse); - if (!token[0]) - break; - } - } - // - // fragmentProgram .... - // - else if (!Q_stricmp(token, "fragmentProgram")) { - token = COM_ParseExt(text, qfalse); - - if (!vertexShaders) { - while (token[0]) - token = COM_ParseExt(text, qfalse); - - continue; - } - - if (!token[0]) { - ri.Printf(PRINT_WARNING, "WARNING: missing parameter(s) for 'fragmentProgram' keyword in shader '%s'\n", shader.name); - return qfalse; - } - - // parse up to MAX_PROGRAM_OBJECTS files - for(;;) { - if (numFragmentObjects < MAX_PROGRAM_OBJECTS) { - Q_strncpyz(programFragmentObjects[numFragmentObjects], token, sizeof(programFragmentObjects[numFragmentObjects])); - numFragmentObjects++; - } else { - ri.Printf(PRINT_WARNING, "WARNING: Too many parameters for 'fragmentProgram' keyword in shader '%s'\n", shader.name); - return qfalse; - } - - token = COM_ParseExt(text, qfalse); - if (!token[0]) - break; - } - } - else if ( !Q_stricmp( token, "mipOffset" ) ){ - token = COM_ParseExt(text,qfalse); - stage->mipBias = atoi(token); - } - else if ( !Q_stricmp( token, "nomipmaps" ) ){ - stageMipmaps = qfalse; - } - // - // map - // - else if ( !Q_stricmp( token, "map" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'map' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if ( !Q_stricmp( token, "$whiteimage" ) ) - { - stage->bundle[0].image[0] = tr.whiteImage; - continue; - } - else if ( !Q_stricmp( token, "$lightmap" ) ) - { - stage->bundle[0].isLightmap = qtrue; - if ( shader.lightmapIndex < 0 || !tr.lightmaps ) { - stage->bundle[0].image[0] = tr.whiteImage; - } else { - stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; - } - continue; - } - else - { - imgType_t type = IMGTYPE_COLORALPHA; - imgFlags_t flags = IMGFLAG_NONE; - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - //stage->bundle[0].image[0] = R_FindImageFile( token, type, flags ); - stage->bundle[0].image[0] = tr.whiteImage; - COM_StripExtension( token, imageName, MAX_QPATH ); - itype = type; iflags = flags; - loadlater = 1; -// imageName = va("%s",token); - - // if ( !stage->bundle[0].image[0] ) - // { - // ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); - // return qfalse; - // } - } - } - // - // clampmap - // - else if ( !Q_stricmp( token, "clampmap" ) ) - { - imgType_t type = IMGTYPE_COLORALPHA; - imgFlags_t flags = IMGFLAG_CLAMPTOEDGE; - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) { - flags |= IMGFLAG_PICMIP; - } - - stage->bundle[0].image[0] = tr.whiteImage; - COM_StripExtension( token, imageName, MAX_QPATH ); - itype = type; iflags = flags; - loadlater = 1; - } - // - // animMap .... - // - else if ( !Q_stricmp( token, "animMap" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'animMmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - stage->bundle[0].imageAnimationSpeed = atof( token ); - - // parse up to MAX_IMAGE_ANIMATIONS animations - while ( 1 ) { - int num; - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) { - break; - } - num = stage->bundle[0].numImageAnimations; - if ( num < MAX_IMAGE_ANIMATIONS ) { - imgFlags_t flags = IMGFLAG_NONE; - - if (!shader.noMipMaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - //stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); - stage->bundle[0].image[num] = tr.whiteImage; - if(num == 0) COM_StripExtension( token, imageNameAnim0, MAX_QPATH ); - if(num == 1) COM_StripExtension( token, imageNameAnim1, MAX_QPATH ); - if(num == 2) COM_StripExtension( token, imageNameAnim2, MAX_QPATH ); - if(num == 3) COM_StripExtension( token, imageNameAnim3, MAX_QPATH ); - if(num == 4) COM_StripExtension( token, imageNameAnim4, MAX_QPATH ); - if(num == 5) COM_StripExtension( token, imageNameAnim5, MAX_QPATH ); - if(num == 6) COM_StripExtension( token, imageNameAnim6, MAX_QPATH ); - if(num == 7) COM_StripExtension( token, imageNameAnim7, MAX_QPATH ); - if(num == 8) COM_StripExtension( token, imageNameAnim8, MAX_QPATH ); - iflags = flags; - loadlater = 1; - stage->bundle[0].numImageAnimations++; - } - } - } - else if ( !Q_stricmp( token, "clampAnimMap" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'clampAnimMmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - stage->bundle[0].imageAnimationSpeed = atof( token ); - - // parse up to MAX_IMAGE_ANIMATIONS animations - while ( 1 ) { - int num; - - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) { - break; - } - num = stage->bundle[0].numImageAnimations; - if ( num < MAX_IMAGE_ANIMATIONS ) { - imgFlags_t flags = IMGFLAG_SRGB; - - if (stageMipmaps) - flags |= IMGFLAG_MIPMAP; - - if (!shader.noPicMip) - flags |= IMGFLAG_PICMIP; - - stage->bundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); - - if ( !stage->bundle[0].image[num] ) - { - ri.Printf( PRINT_WARNING, "WARNING: R_FindImageFile could not find '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - stage->bundle[0].numImageAnimations++; - } - } - } - else if ( !Q_stricmp( token, "videoMap" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMmap' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); - if (stage->bundle[0].videoMapHandle != -1) { - stage->bundle[0].isVideoMap = qtrue; - stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle]; - } - } - // - // alphafunc - // - else if ( !Q_stricmp( token, "alphaFunc" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'alphaFunc' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - atestBits = NameToAFunc( token ); - } - // - // depthFunc - // - else if ( !Q_stricmp( token, "depthfunc" ) ) - { - token = COM_ParseExt( text, qfalse ); - - if ( !token[0] ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'depthfunc' keyword in shader '%s'\n", shader.name ); - return qfalse; - } - - if ( !Q_stricmp( token, "lequal" ) ) - { - depthFuncBits = 0; - } - else if ( !Q_stricmp( token, "equal" ) ) - { - depthFuncBits = GLS_DEPTHFUNC_EQUAL; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown depthfunc '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // detail - // - else if ( !Q_stricmp( token, "detail" ) ) - { - stage->isDetail = qtrue; - } - // - // blendfunc - // or blendfunc - // - else if ( !Q_stricmp( token, "blendfunc" ) ) - { - hackoperation = 0; - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); - hackoperation = 0; - continue; - } - // check for "simple" blends first - if ( !Q_stricmp( token, "add" ) ) { - blendSrcBits = GLS_SRCBLEND_ONE; - blendDstBits = GLS_DSTBLEND_ONE; - hackoperation = 1; - } else if ( !Q_stricmp( token, "filter" ) ) { - blendSrcBits = GLS_SRCBLEND_DST_COLOR; - blendDstBits = GLS_DSTBLEND_ZERO; - // hackoperation = 4; - } else if ( !Q_stricmp( token, "blend" ) ) { - blendSrcBits = GLS_SRCBLEND_SRC_ALPHA; - blendDstBits = GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; - hackoperation = 0; - - } else { - // complex double blends - blendSrcBits = NameToSrcBlendMode( token ); - hackoperation = 0; - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parm for blendFunc in shader '%s'\n", shader.name ); - continue; - } - blendDstBits = NameToDstBlendMode( token ); - } - - stage->isBlend = 1; // 2x2 - - // clear depth mask for blended surfaces - if ( !depthMaskExplicit ) - { - depthMaskBits = 0; - } - - - } - // - // rgbGen - // - else if ( !Q_stricmp( token, "rgbGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameters for rgbGen in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "wave" ) ) - { - ParseWaveForm( text, &stage->rgbWave ); - stage->rgbGen = CGEN_WAVEFORM; - } - else if ( !Q_stricmp( token, "const" ) ) - { - vec3_t color; - - ParseVector( text, 3, color ); - stage->constantColor[0] = 255 * color[0]; - stage->constantColor[1] = 255 * color[1]; - stage->constantColor[2] = 255 * color[2]; - - stage->rgbGen = CGEN_CONST; - } - else if ( !Q_stricmp( token, "identity" ) ) - { - stage->rgbGen = CGEN_IDENTITY; - } - else if ( !Q_stricmp( token, "identityLighting" ) ) - { - stage->rgbGen = CGEN_IDENTITY_LIGHTING; - } - else if ( !Q_stricmp( token, "entity" ) ) - { - stage->rgbGen = CGEN_ENTITY; - } - else if ( !Q_stricmp( token, "oneMinusEntity" ) ) - { - stage->rgbGen = CGEN_ONE_MINUS_ENTITY; - } - else if ( !Q_stricmp( token, "vertex" ) ) - { - stage->rgbGen = CGEN_VERTEX; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "exactVertex" ) ) - { - stage->rgbGen = CGEN_EXACT_VERTEX; - } - else if ( !Q_stricmp( token, "vertexLighting" ) ) // leilei - vertex WITH a lighting pass after - { - stage->rgbGen = CGEN_VERTEX_LIT; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "vertexLighting2" ) ) // leilei - second vertex color - { - stage->rgbGen = CGEN_VERTEX_LIT; - if ( stage->alphaGen == 0 ) { - stage->alphaGen = AGEN_VERTEX; - } - } - else if ( !Q_stricmp( token, "lightingDiffuse" ) ) - { - stage->rgbGen = CGEN_LIGHTING_DIFFUSE; - } - else if ( !Q_stricmp( token, "lightingUniform" ) ) - { - stage->rgbGen = CGEN_LIGHTING_UNIFORM; - } - else if ( !Q_stricmp( token, "lightingDynamic" ) ) - { - stage->rgbGen = CGEN_LIGHTING_DYNAMIC; - } - else if ( !Q_stricmp( token, "flatAmbient" ) ) - { - stage->rgbGen = CGEN_LIGHTING_FLAT_AMBIENT; - } - else if ( !Q_stricmp( token, "flatDirect" ) ) - { - stage->rgbGen = CGEN_LIGHTING_FLAT_DIRECT; - } - else if ( !Q_stricmp( token, "oneMinusVertex" ) ) - { - stage->rgbGen = CGEN_ONE_MINUS_VERTEX; - } - else if ( !Q_stricmp( token, "lightingSpecularDiffuse" ) ) // leilei - deprecated - { - stage->rgbGen = CGEN_LIGHTING_DIFFUSE; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown rgbGen parameter '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // alphaGen - // - else if ( !Q_stricmp( token, "alphaGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing parameters for alphaGen in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "wave" ) ) - { - ParseWaveForm( text, &stage->alphaWave ); - stage->alphaGen = AGEN_WAVEFORM; - } - else if ( !Q_stricmp( token, "const" ) ) - { - token = COM_ParseExt( text, qfalse ); - stage->constantColor[3] = 255 * atof( token ); - stage->alphaGen = AGEN_CONST; - } - else if ( !Q_stricmp( token, "identity" ) ) - { - stage->alphaGen = AGEN_IDENTITY; - } - else if ( !Q_stricmp( token, "entity" ) ) - { - stage->alphaGen = AGEN_ENTITY; - } - else if ( !Q_stricmp( token, "oneMinusEntity" ) ) - { - stage->alphaGen = AGEN_ONE_MINUS_ENTITY; - } - else if ( !Q_stricmp( token, "vertex" ) ) - { - stage->alphaGen = AGEN_VERTEX; - } - else if ( !Q_stricmp( token, "lightingSpecular" ) ) - { - stage->alphaGen = AGEN_LIGHTING_SPECULAR; - } - else if ( !Q_stricmp( token, "oneMinusVertex" ) ) - { - stage->alphaGen = AGEN_ONE_MINUS_VERTEX; - } - else if ( !Q_stricmp( token, "portal" ) ) - { - stage->alphaGen = AGEN_PORTAL; - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - shader.portalRange = 256; - ri.Printf( PRINT_WARNING, "WARNING: missing range parameter for alphaGen portal in shader '%s', defaulting to 256\n", shader.name ); - } - else - { - shader.portalRange = atof( token ); - } - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown alphaGen parameter '%s' in shader '%s'\n", token, shader.name ); - continue; - } - } - // - // tcGen - // - else if ( !Q_stricmp(token, "texgen") || !Q_stricmp( token, "tcGen" ) ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - { - ri.Printf( PRINT_WARNING, "WARNING: missing texgen parm in shader '%s'\n", shader.name ); - continue; - } - - if ( !Q_stricmp( token, "environment" ) ) - { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; - } - else if ( !Q_stricmp( token, "cel" ) ) - { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_CELSHADE_MAPPED; - } - else if ( !Q_stricmp( token, "celshading" ) ) // leilei - my technique is different - { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_CELSHADE_LEILEI; - } - else if ( !Q_stricmp( token, "eyeleft" ) ) // leilei - eye tracking - { - stage->bundle[0].tcGen = TCGEN_EYE_LEFT; - } - else if ( !Q_stricmp( token, "eyeright" ) ) // leilei - eye tracking - { - stage->bundle[0].tcGen = TCGEN_EYE_RIGHT; - } - else if ( !Q_stricmp( token, "environmentWater" ) ) - { - stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED_WATER; // leilei - water's envmaps - } - else if ( !Q_stricmp( token, "lightmap" ) ) - { - stage->bundle[0].tcGen = TCGEN_LIGHTMAP; - } - else if ( !Q_stricmp( token, "texture" ) || !Q_stricmp( token, "base" ) ) - { - stage->bundle[0].tcGen = TCGEN_TEXTURE; - } - else if ( !Q_stricmp( token, "vector" ) ) - { - ParseVector( text, 3, stage->bundle[0].tcGenVectors[0] ); - ParseVector( text, 3, stage->bundle[0].tcGenVectors[1] ); - - stage->bundle[0].tcGen = TCGEN_VECTOR; - } - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown texgen parm in shader '%s'\n", shader.name ); - } - } - // - // tcMod <...> - // - else if ( !Q_stricmp( token, "tcMod" ) ) - { - char buffer[1024] = ""; - - while ( 1 ) - { - token = COM_ParseExt( text, qfalse ); - if ( token[0] == 0 ) - break; - strcat( buffer, token ); - strcat( buffer, " " ); - } - - ParseTexMod( buffer, stage ); - - continue; - } - // - // depthmask - // - else if ( !Q_stricmp( token, "depthwrite" ) ) - { - depthMaskBits = GLS_DEPTHMASK_TRUE; - depthMaskExplicit = qtrue; - - continue; - } - - else - { - ri.Printf( PRINT_WARNING, "WARNING: unknown parameter '%s' in shader '%s'\n", token, shader.name ); - return qfalse; - } - - - - - } - - // - // if cgen isn't explicitly specified, use either identity or identitylighting - // - if ( stage->rgbGen == CGEN_BAD ) { - if ( blendSrcBits == 0 || - blendSrcBits == GLS_SRCBLEND_ONE || - blendSrcBits == GLS_SRCBLEND_SRC_ALPHA ) { - stage->rgbGen = CGEN_IDENTITY_LIGHTING; - } else { - stage->rgbGen = CGEN_IDENTITY; - } - } - - - // - // implicitly assume that a GL_ONE GL_ZERO blend mask disables blending - // - if ( ( blendSrcBits == GLS_SRCBLEND_ONE ) && - ( blendDstBits == GLS_DSTBLEND_ZERO ) ) - { - blendDstBits = blendSrcBits = 0; - depthMaskBits = GLS_DEPTHMASK_TRUE; - } - - // decide which agens we can skip - if ( stage->alphaGen == AGEN_IDENTITY ) { - if ( stage->rgbGen == CGEN_IDENTITY - || stage->rgbGen == CGEN_LIGHTING_DIFFUSE - || stage->rgbGen == CGEN_LIGHTING_UNIFORM - || stage->rgbGen == CGEN_LIGHTING_DYNAMIC) { - stage->alphaGen = AGEN_SKIP; - } - } - - // - // compute state bits - // - stage->stateBits = depthMaskBits | - blendSrcBits | blendDstBits | - atestBits | - depthFuncBits; - // - // now load our image! - // - - //hackoperation = 2; - if (loadlater){ - if (!blendDstBits) hackoperation = 2; - - if (ismaptexture){ - - if (surfaceflagsy & CONTENTS_TRANSLUCENT) - hackoperation = 0; - else - hackoperation = 2; - } - - if (blendSrcBits == GLS_SRCBLEND_ONE) hackoperation = 1; - if (blendDstBits == GLS_DSTBLEND_ONE) hackoperation = 1; - - - if (blendSrcBits == GLS_SRCBLEND_SRC_ALPHA) hackoperation = 0; - if (blendDstBits == GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA) hackoperation = 0; - - if (blendSrcBits == GLS_SRCBLEND_DST_COLOR && - blendDstBits == GLS_DSTBLEND_SRC_COLOR) - hackoperation = 4; - - if (blendSrcBits == GLS_SRCBLEND_DST_COLOR && - blendDstBits == GLS_SRCBLEND_ONE) - hackoperation = 1; - - if (blendSrcBits == GLS_SRCBLEND_SRC_ALPHA && - blendDstBits == GLS_SRCBLEND_ONE) // additive, but blended away by alpha - hackoperation = 1; - - - if (!ismaptexture){ - if (blendSrcBits == GLS_SRCBLEND_ZERO) hackoperation = 3; - //if (blendDstBits == GLS_DSTBLEND_ZERO) hackoperation = 3; - } - if (stage->bundle[0].numImageAnimations>0){ - int n, o; - n= stage->bundle[0].numImageAnimations; - for (o=0; obundle[0].image[num] = R_FindImageFile( token, IMGTYPE_COLORALPHA, flags ); - - if(o == 0) COM_StripExtension( imageNameAnim0, imageName, MAX_QPATH ); - if(o == 1) COM_StripExtension( imageNameAnim1, imageName, MAX_QPATH ); - if(o == 2) COM_StripExtension( imageNameAnim2, imageName, MAX_QPATH ); - if(o == 3) COM_StripExtension( imageNameAnim3, imageName, MAX_QPATH ); - if(o == 4) COM_StripExtension( imageNameAnim4, imageName, MAX_QPATH ); - if(o == 5) COM_StripExtension( imageNameAnim5, imageName, MAX_QPATH ); - if(o == 6) COM_StripExtension( imageNameAnim6, imageName, MAX_QPATH ); - if(o == 7) COM_StripExtension( imageNameAnim7, imageName, MAX_QPATH ); - if(o == 8) COM_StripExtension( imageNameAnim8, imageName, MAX_QPATH ); - stage->bundle[0].image[o] = R_FindImageFile( imageName, itype, iflags ); - - } - } - else - stage->bundle[0].image[0] = R_FindImageFile( imageName, itype, iflags ); - stage->isBlend = hackoperation; - - if (blendSrcBits == GLS_SRCBLEND_SRC_ALPHA && - blendDstBits == GLS_SRCBLEND_ONE) // additive, but blended away by alpha - stage->isBlend = 0; - - } - - return qtrue; -} - /* =============== @@ -4802,7 +4263,8 @@ static void VertexLightingCollapse( void ) { if ( shader.lightmapIndex == LIGHTMAP_NONE ) { stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; } else { - stages[0].rgbGen = CGEN_EXACT_VERTEX; + stages[0].rgbGen = CGEN_VERTEX_LIT;// leilei - dynamic lights in vertex lighting + //stages[0].rgbGen = CGEN_EXACT_VERTEX; } stages[0].alphaGen = AGEN_SKIP; } else { @@ -4971,18 +4433,6 @@ static shader_t *FinishShader( void ) { // vertexLightmap = qtrue; //} - -#ifdef GLSL_TEXTURES - - // leilei - force new phong on lightdiffuse and lightdiffusespecular models - // FIXME: Intel HD doesn't like this. - if ((r_modelshader->integer) && (pStage->isGLSL==0) && (r_ext_vertex_shader->integer) && ((pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) || (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE_SPECULAR))) - { - pStage->program = RE_GLSL_RegisterProgram("leishade", "glsl/leishade_vp.glsl", 1, "glsl/leishade_fp.glsl", 1); - pStage->isGLSL=1; - pStage->isLeiShade=1; - } -#endif // // determine sort order and fog color adjustment // @@ -5444,71 +4894,6 @@ shader_t *R_FindShaderReal( const char *name, int lightmapIndex, qboolean mipRaw // create the default shading commands // - if (r_parseStageSimple->integer){ // leilei - for powervr - hackoperation = 0; - - if ( shader.lightmapIndex == LIGHTMAP_NONE ) { - // dynamic colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_LIGHTING_DIFFUSE; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_BY_VERTEX ) { - // explicit colors at vertexes - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_EXACT_VERTEX; - stages[0].alphaGen = AGEN_SKIP; - stages[0].stateBits = GLS_DEFAULT; - } else if ( shader.lightmapIndex == LIGHTMAP_2D ) { - // GUI elements - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_VERTEX; - stages[0].alphaGen = AGEN_VERTEX; - stages[0].stateBits = GLS_DEPTHTEST_DISABLE; - stages[0].isBlend = 0; - hackoperation = 0; - } else if ( shader.lightmapIndex == LIGHTMAP_WHITEIMAGE ) { - // fullbright level - stages[1].bundle[0].image[0] = tr.whiteImage; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY_LIGHTING; - stages[1].stateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_DST_ALPHA; - - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY; - stages[0].stateBits = GLS_DEFAULT; - } else { - - // two pass lightmap - - hackoperation = 0; - stages[0].isBlend = 0; - stages[0].bundle[0].image[0] = image; - stages[0].active = qtrue; - stages[0].rgbGen = CGEN_IDENTITY; - stages[0].stateBits = GLS_DEFAULT; - - hackoperation = 4; - stages[1].bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; - stages[1].bundle[0].isLightmap = qtrue; - stages[1].active = qtrue; - stages[1].rgbGen = CGEN_IDENTITY; // lightmaps are scaled on creation - stages[1].isBlend = 1; - // for identitylight - stages[1].stateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_DST_ALPHA; - - - } - - - - } - else // normal - { - if ( shader.lightmapIndex == LIGHTMAP_NONE ) { // dynamic colors at vertexes stages[0].bundle[0].image[0] = image; @@ -5519,7 +4904,8 @@ shader_t *R_FindShaderReal( const char *name, int lightmapIndex, qboolean mipRaw // explicit colors at vertexes stages[0].bundle[0].image[0] = image; stages[0].active = qtrue; - stages[0].rgbGen = CGEN_EXACT_VERTEX; + stages[0].rgbGen = CGEN_VERTEX_LIT;// leilei - dynamic lights in vertex lighting + //stages[0].rgbGen = CGEN_EXACT_VERTEX; stages[0].alphaGen = AGEN_SKIP; stages[0].stateBits = GLS_DEFAULT; } else if ( shader.lightmapIndex == LIGHTMAP_2D ) { @@ -5561,7 +4947,6 @@ shader_t *R_FindShaderReal( const char *name, int lightmapIndex, qboolean mipRaw // detail { int f; - if (r_parseStageSimple->integer) hackoperation = 4; for (f=0;f MAX_SHADER_STAGES) break;// don't exceed limit! @@ -5604,7 +4989,6 @@ shader_t *R_FindShaderReal( const char *name, int lightmapIndex, qboolean mipRaw stages[1].rgbGen = CGEN_IDENTITY; stages[1].stateBits |= GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO; } - } // leilei - handle image height @@ -5625,20 +5009,10 @@ shader_t *R_FindShaderReal( const char *name, int lightmapIndex, qboolean mipRaw return FinishShader(); } -// leilei - rather stupid way to do a cel wrapper to work for all textures shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { shader_t *sh; shader_t *ahsh; -/* // Sadly, I have deprecated the old cel hack. I am leaving it here. It breaks 2D textures BTW!!! :( - if (r_anime->integer){ - sh = R_FindShaderReal(va("%s_cel",name), lightmapIndex, mipRawImage); - if ( sh->defaultShader ) - sh = R_FindShaderReal(name, lightmapIndex, mipRawImage); - return sh; - } - else*/ - // load real shader first? sh = R_FindShaderReal(name, lightmapIndex, mipRawImage); if (!Q_strncmp( name, "models/player", 13) ){ // restrict to players; speedup @@ -5729,7 +5103,8 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_ // explicit colors at vertexes stages[0].bundle[0].image[0] = image; stages[0].active = qtrue; - stages[0].rgbGen = CGEN_EXACT_VERTEX; + stages[0].rgbGen = CGEN_VERTEX_LIT;// leilei - dynamic lights in vertex lighting + //stages[0].rgbGen = CGEN_EXACT_VERTEX; stages[0].alphaGen = AGEN_SKIP; stages[0].stateBits = GLS_DEFAULT; } else if ( shader.lightmapIndex == LIGHTMAP_2D ) { diff --git a/code/renderer_oa/tr_sky.c b/code/renderer_oa/tr_sky.c index b955230b..f09d69c6 100644 --- a/code/renderer_oa/tr_sky.c +++ b/code/renderer_oa/tr_sky.c @@ -25,6 +25,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define SKY_SUBDIVISIONS 8 #define HALF_SKY_SUBDIVISIONS (SKY_SUBDIVISIONS/2) +// leilei - optimizing sky +static int SkySub = 8; +static int HalfSkySub = 4; + static float s_cloudTexCoords[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1][2]; static float s_cloudTexP[6][SKY_SUBDIVISIONS+1][SKY_SUBDIVISIONS+1]; @@ -309,6 +313,7 @@ static void MakeSkyVec( float s, float t, int axis, float outSt[2], vec3_t outXY float boxSize; boxSize = backEnd.viewParms.zFar / 1.75; // div sqrt(3) + b[0] = s*boxSize; b[1] = t*boxSize; b[2] = boxSize; @@ -367,11 +372,11 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max GL_Bind( image ); - for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t < maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) + for ( t = mins[1]+HalfSkySub; t < maxs[1]+HalfSkySub; t++ ) { qglBegin( GL_TRIANGLE_STRIP ); - for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) + for ( s = mins[0]+HalfSkySub; s <= maxs[0]+HalfSkySub; s++ ) { qglTexCoord2fv( s_skyTexCoords[t][s] ); qglVertex3fv( s_skyPoints[t][s] ); @@ -398,10 +403,10 @@ static void DrawSkyBox( shader_t *shader ) int sky_mins_subd[2], sky_maxs_subd[2]; int s, t; - sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_mins[0][i] = floor( sky_mins[0][i] * HalfSkySub ) / HalfSkySub; + sky_mins[1][i] = floor( sky_mins[1][i] * HalfSkySub ) / HalfSkySub; + sky_maxs[0][i] = ceil( sky_maxs[0][i] * HalfSkySub ) / HalfSkySub; + sky_maxs[1][i] = ceil( sky_maxs[1][i] * HalfSkySub ) / HalfSkySub; if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || ( sky_mins[1][i] >= sky_maxs[1][i] ) ) @@ -409,38 +414,38 @@ static void DrawSkyBox( shader_t *shader ) continue; } - sky_mins_subd[0] = sky_mins[0][i] * HALF_SKY_SUBDIVISIONS; - sky_mins_subd[1] = sky_mins[1][i] * HALF_SKY_SUBDIVISIONS; - sky_maxs_subd[0] = sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS; - sky_maxs_subd[1] = sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS; + sky_mins_subd[0] = sky_mins[0][i] * HalfSkySub; + sky_mins_subd[1] = sky_mins[1][i] * HalfSkySub; + sky_maxs_subd[0] = sky_maxs[0][i] * HalfSkySub; + sky_maxs_subd[1] = sky_maxs[1][i] * HalfSkySub; - if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_mins_subd[1] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; + if ( sky_mins_subd[0] < -HalfSkySub ) + sky_mins_subd[0] = -HalfSkySub; + else if ( sky_mins_subd[0] > HalfSkySub ) + sky_mins_subd[0] = HalfSkySub; + if ( sky_mins_subd[1] < -HalfSkySub ) + sky_mins_subd[1] = -HalfSkySub; + else if ( sky_mins_subd[1] > HalfSkySub ) + sky_mins_subd[1] = HalfSkySub; - if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; - if ( sky_maxs_subd[1] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; + if ( sky_maxs_subd[0] < -HalfSkySub ) + sky_maxs_subd[0] = -HalfSkySub; + else if ( sky_maxs_subd[0] > HalfSkySub ) + sky_maxs_subd[0] = HalfSkySub; + if ( sky_maxs_subd[1] < -HalfSkySub ) + sky_maxs_subd[1] = -HalfSkySub; + else if ( sky_maxs_subd[1] > HalfSkySub ) + sky_maxs_subd[1] = HalfSkySub; // // iterate through the subdivisions // - for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) + for ( t = sky_mins_subd[1]+HalfSkySub; t <= sky_maxs_subd[1]+HalfSkySub; t++ ) { - for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) + for ( s = sky_mins_subd[0]+HalfSkySub; s <= sky_maxs_subd[0]+HalfSkySub; s++ ) { - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + MakeSkyVec( ( s - HalfSkySub ) / ( float ) HalfSkySub, + ( t - HalfSkySub ) / ( float ) HalfSkySub, i, s_skyTexCoords[t][s], s_skyPoints[t][s] ); @@ -463,9 +468,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; - for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) + for ( t = mins[1]+HalfSkySub; t <= maxs[1]+HalfSkySub; t++ ) { - for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) + for ( s = mins[0]+HalfSkySub; s <= maxs[0]+HalfSkySub; s++ ) { VectorAdd( s_skyPoints[t][s], backEnd.viewParms.or.origin, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; @@ -516,7 +521,7 @@ static void FillCloudBox( const shader_t *shader, int stage ) if ( 1 ) // FIXME? shader->sky.fullClouds ) { - MIN_T = -HALF_SKY_SUBDIVISIONS; + MIN_T = -HalfSkySub; // still don't want to draw the bottom, even if fullClouds if ( i == 5 ) @@ -537,15 +542,15 @@ static void FillCloudBox( const shader_t *shader, int stage ) continue; case 4: // top default: - MIN_T = -HALF_SKY_SUBDIVISIONS; + MIN_T = -HalfSkySub; break; } } - sky_mins[0][i] = floor( sky_mins[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_mins[1][i] = floor( sky_mins[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[0][i] = ceil( sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; - sky_maxs[1][i] = ceil( sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS ) / HALF_SKY_SUBDIVISIONS; + sky_mins[0][i] = floor( sky_mins[0][i] * HalfSkySub ) / HalfSkySub; + sky_mins[1][i] = floor( sky_mins[1][i] * HalfSkySub ) / HalfSkySub; + sky_maxs[0][i] = ceil( sky_maxs[0][i] * HalfSkySub ) / HalfSkySub; + sky_maxs[1][i] = ceil( sky_maxs[1][i] * HalfSkySub ) / HalfSkySub; if ( ( sky_mins[0][i] >= sky_maxs[0][i] ) || ( sky_mins[1][i] >= sky_maxs[1][i] ) ) @@ -553,38 +558,38 @@ static void FillCloudBox( const shader_t *shader, int stage ) continue; } - sky_mins_subd[0] = ri.ftol(sky_mins[0][i] * HALF_SKY_SUBDIVISIONS); - sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HALF_SKY_SUBDIVISIONS); - sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HALF_SKY_SUBDIVISIONS); - sky_maxs_subd[1] = ri.ftol(sky_maxs[1][i] * HALF_SKY_SUBDIVISIONS); + sky_mins_subd[0] = ri.ftol(sky_mins[0][i] * HalfSkySub); + sky_mins_subd[1] = ri.ftol(sky_mins[1][i] * HalfSkySub); + sky_maxs_subd[0] = ri.ftol(sky_maxs[0][i] * HalfSkySub); + sky_maxs_subd[1] = ri.ftol(sky_maxs[1][i] * HalfSkySub); - if ( sky_mins_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_mins_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_mins_subd[0] < -HalfSkySub ) + sky_mins_subd[0] = -HalfSkySub; + else if ( sky_mins_subd[0] > HalfSkySub ) + sky_mins_subd[0] = HalfSkySub; if ( sky_mins_subd[1] < MIN_T ) sky_mins_subd[1] = MIN_T; - else if ( sky_mins_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_mins_subd[1] = HALF_SKY_SUBDIVISIONS; + else if ( sky_mins_subd[1] > HalfSkySub ) + sky_mins_subd[1] = HalfSkySub; - if ( sky_maxs_subd[0] < -HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = -HALF_SKY_SUBDIVISIONS; - else if ( sky_maxs_subd[0] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[0] = HALF_SKY_SUBDIVISIONS; + if ( sky_maxs_subd[0] < -HalfSkySub ) + sky_maxs_subd[0] = -HalfSkySub; + else if ( sky_maxs_subd[0] > HalfSkySub ) + sky_maxs_subd[0] = HalfSkySub; if ( sky_maxs_subd[1] < MIN_T ) sky_maxs_subd[1] = MIN_T; - else if ( sky_maxs_subd[1] > HALF_SKY_SUBDIVISIONS ) - sky_maxs_subd[1] = HALF_SKY_SUBDIVISIONS; + else if ( sky_maxs_subd[1] > HalfSkySub ) + sky_maxs_subd[1] = HalfSkySub; // // iterate through the subdivisions // - for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t <= sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) + for ( t = sky_mins_subd[1]+HalfSkySub; t <= sky_maxs_subd[1]+HalfSkySub; t++ ) { - for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s <= sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ ) + for ( s = sky_mins_subd[0]+HalfSkySub; s <= sky_maxs_subd[0]+HalfSkySub; s++ ) { - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + MakeSkyVec( ( s - HalfSkySub ) / ( float ) HalfSkySub, + ( t - HalfSkySub ) / ( float ) HalfSkySub, i, NULL, s_skyPoints[t][s] ); @@ -644,19 +649,30 @@ void R_InitSkyTexCoords( float heightCloud ) vec3_t skyVec; vec3_t v; + + // leilei - sky optimizations + SkySub = r_skytess->integer; + HalfSkySub = r_skytess->integer / 2; + + if (SkySub < 2) SkySub = 2; + if (SkySub > 8) SkySub = 8; + if (HalfSkySub < 1) HalfSkySub = 1; + if (HalfSkySub > 4) HalfSkySub = 4; + + // init zfar so MakeSkyVec works even though // a world hasn't been bounded backEnd.viewParms.zFar = 1024; for ( i = 0; i < 6; i++ ) { - for ( t = 0; t <= SKY_SUBDIVISIONS; t++ ) + for ( t = 0; t <= SkySub; t++ ) { - for ( s = 0; s <= SKY_SUBDIVISIONS; s++ ) + for ( s = 0; s <= SkySub; s++ ) { // compute vector from view origin to sky side integral point - MakeSkyVec( ( s - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, - ( t - HALF_SKY_SUBDIVISIONS ) / ( float ) HALF_SKY_SUBDIVISIONS, + MakeSkyVec( ( s - HalfSkySub ) / ( float ) HalfSkySub, + ( t - HalfSkySub ) / ( float ) HalfSkySub, i, NULL, skyVec ); @@ -705,6 +721,7 @@ void RB_DrawSun( void ) { if ( !backEnd.skyRenderedThisView ) { return; } + // TODO: Add a sun check for sky shaders explicitly requesting for the sun, to keep compatibility with sun-less skies. if ( !r_drawSun->integer ) { return; } @@ -838,7 +855,9 @@ void RB_StageIteratorSky( void ) { // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in - if ( r_showsky->integer ) { + if ( r_showsky->integer == 2) { + qglDepthRange( 0.0, 1.0 ); // leilei - pvr1 imitation + } else if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); diff --git a/code/sdl/sdl_glimp.c b/code/sdl/sdl_glimp.c index d1c1ae57..a5d427a5 100644 --- a/code/sdl/sdl_glimp.c +++ b/code/sdl/sdl_glimp.c @@ -51,12 +51,6 @@ typedef void *QGLContext; static QGLContext opengl_context; #endif -int tvMode; // leilei - tvmode -int tvWidth; -int tvHeight; -int tvinterlace = 1; // leilei - interlace value for height -float tvAspectW; // leilei - for aspect correction - //int vresWidth; //int vresHeight; @@ -80,11 +74,6 @@ static const SDL_VideoInfo *videoInfo = NULL; #endif cvar_t *r_allowSoftwareGL; // Don't abort out if a hardware visual can't be obtained -cvar_t *r_tvMode; // leilei - tv mode - force 480i rendering, which is then stretched and interlaced -cvar_t *r_tvFilter; // leilei - tv filter -cvar_t *r_tvModeAspect; // leilei - tv mode - to do widescreen and low res tv etc -cvar_t *r_tvModeForceAspect; // leilei - tv mode - to force the screen into its native aspect -cvar_t *r_motionblur; // leilei - moved here to set up accumulation bits cvar_t *r_allowResize; // make window resizable cvar_t *r_conMode; // leilei - console mode - force native resolutions of various consoles cvar_t *r_centerWindow; @@ -280,7 +269,6 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) int sdlcolorbits; int colorbits, depthbits, stencilbits; int tcolorbits, tdepthbits, tstencilbits; - int accumbits; // leilei - motionblur int samples; int i = 0; SDL_Surface *icon = NULL; @@ -438,12 +426,6 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) stencilbits = r_stencilbits->value; samples = r_ext_multisample->value; - // leilei - motion blur via accumulation buffer support - if (r_motionblur->integer == 1) - accumbits = 16; - else - accumbits = 0; - for (i = 0; i < 16; i++) { // 0 - default @@ -519,12 +501,6 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, tdepthbits ); SDL_GL_SetAttribute( SDL_GL_STENCIL_SIZE, tstencilbits ); - // leilei - accumulation buffer motion blur - SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, accumbits ); - SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, accumbits ); - SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, accumbits ); - SDL_GL_SetAttribute( SDL_GL_ACCUM_ALPHA_SIZE, accumbits ); - SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, samples ? 1 : 0 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, samples ); @@ -651,12 +627,6 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) } #endif - // - // leilei - TV MODE - // - tvWidth = glConfig.vidWidth; - tvHeight = glConfig.vidHeight; - vresWidth = glConfig.vidWidth; vresHeight = glConfig.vidHeight; @@ -665,44 +635,10 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) vresWidth = 640; vresHeight = 480; - //tvAspectW = 1.0; // no change - if( r_tvMode->integer > -1){ - - - if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, r_tvMode->integer ) ) - { - glConfig.vidWidth = 640; // if we can't do a mode then do this mode - glConfig.vidHeight = 480; - } - - - if (glConfig.vidWidth > tvWidth) glConfig.vidWidth = tvWidth; // clamp - if (glConfig.vidHeight > tvHeight) glConfig.vidHeight = tvHeight; // clamp - - - // leilei - make it use an aspect-corrected lower resolution that's always 640 wide for the width, but variable height - // then change the gl port.. - - vresWidth = tvWidth; - vresHeight = tvHeight; - - if( r_tvModeForceAspect->integer ){ - float ttw = (float)glConfig.vidWidth / ((float)tvWidth * (float)((float)glConfig.vidHeight/(float)tvHeight)); // 640 / 853 = 0.75 = ASPECT VALUE - tvAspectW = ttw; // let's try this first to see if we can get it to our renderer - //tvAspectW = 0.75f; // let's try this first to see if we can get it to our renderer - } - } - // leilei - tv mode hack end #if SDL_MAJOR_VERSION != 2 screen = vidscreen; #endif - - if( r_tvModeAspect->integer ) { - float aspe = 640.0f / tvWidth; - glConfig.vidWidth = tvWidth * aspe; - glConfig.vidHeight = tvHeight * aspe; - } // then change the gl port.. glstring = (char *) qglGetString (GL_RENDERER); @@ -967,15 +903,6 @@ void GLimp_Init( void ) r_sdlDriver = ri.Cvar_Get( "r_sdlDriver", "", CVAR_ROM ); r_allowResize = ri.Cvar_Get( "r_allowResize", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_centerWindow = ri.Cvar_Get( "r_centerWindow", "0", CVAR_ARCHIVE | CVAR_LATCH ); -// leilei - tv mode hack - r_tvMode = ri.Cvar_Get( "r_virtualMode", "-1", CVAR_LATCH | CVAR_ARCHIVE ); - r_tvModeAspect = ri.Cvar_Get( "r_tvModeAspect", "0", CVAR_LATCH | CVAR_ARCHIVE ); // yes - r_tvModeForceAspect = ri.Cvar_Get( "r_tvModeForceAspect", "0", CVAR_LATCH | CVAR_ARCHIVE ); // yes - - r_tvFilter = ri.Cvar_Get( "r_tvFilter", "1", CVAR_LATCH | CVAR_ARCHIVE ); - -// leilei - move motionblur cvar here to get it to not upset the other renderers when setting up an accumulation buffer - r_motionblur = ri.Cvar_Get( "r_motionblur", "0", CVAR_LATCH | CVAR_ARCHIVE ); if( ri.Cvar_VariableIntegerValue( "com_abnormalExit" ) ) { diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index b6d5257d..2f2a65d1 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -1204,6 +1204,7 @@ static void IN_ProcessEvents( void ) case SDL_WINDOWEVENT_MAXIMIZED: Cvar_SetValue( "com_minimized", 0 ); break; case SDL_WINDOWEVENT_FOCUS_LOST: Cvar_SetValue( "com_unfocused", 1 ); break; case SDL_WINDOWEVENT_FOCUS_GAINED: Cvar_SetValue( "com_unfocused", 0 ); break; + case SDL_WINDOWEVENT_CLOSE: Cbuf_ExecuteText(EXEC_NOW, "quit Closed window\n"); break; } break; #else diff --git a/code/server/sv_init.c b/code/server/sv_init.c index fe07472f..0b819c5a 100644 --- a/code/server/sv_init.c +++ b/code/server/sv_init.c @@ -677,8 +677,7 @@ void SV_Init (void) Cvar_Get ("sv_dlURL", "", CVAR_SERVERINFO | CVAR_ARCHIVE); sv_master[0] = Cvar_Get("sv_master1", MASTER_SERVER_NAME, 0); - sv_master[1] = Cvar_Get("sv_master2", "master.ioquake3.org", 0); - for(index = 2; index < MAX_MASTER_SERVERS; index++) + for(index = 1; index < MAX_MASTER_SERVERS; index++) sv_master[index] = Cvar_Get(va("sv_master%d", index + 1), "", CVAR_ARCHIVE); sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0);