diff --git a/client/client.plg b/client/client.plg new file mode 100644 index 00000000..33666b63 --- /dev/null +++ b/client/client.plg @@ -0,0 +1,16 @@ + + +
+

Build Log

+

+--------------------Configuration: client - Win32 Debug-------------------- +

+

Command Lines

+ + + +

Results

+client.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/client/global/utils.cpp b/client/global/utils.cpp index de98919d..ff0777ec 100644 --- a/client/global/utils.cpp +++ b/client/global/utils.cpp @@ -298,7 +298,7 @@ client_sprite_t *SPR_GetList( const char *psz, int *piCount ) *piCount = iSprCount; return NULL; } - + char *token; const char *plist = pfile; int depth = 0; @@ -564,7 +564,7 @@ void V_RenderPlaque( void ) const char *levelshot; levelshot = CVAR_GET_STRING( "cl_levelshot_name" ); - if( !strcmp( levelshot, "" )) levelshot = "$blackimage"; + if( !strcmp( levelshot, "" )) levelshot = "*black"; // logo that shows up while upload next level DrawImageRectangle( SPR_Load( levelshot )); diff --git a/client/hud/hud.cpp b/client/hud/hud.cpp index 7b774dc0..86d43ca6 100644 --- a/client/hud/hud.cpp +++ b/client/hud/hud.cpp @@ -123,7 +123,7 @@ void CHud :: VidInit( void ) } else { - ALERT( at_warning, "hud.shader couldn't load\n" ); + ALERT( at_warning, "hud.txt couldn't load\n" ); CVAR_SET_FLOAT( "hud_draw", 0 ); return; } @@ -283,7 +283,7 @@ int CHud :: Redraw( float flTime ) if( !m_iIntermission ) { if(( pList->p->m_iFlags & HUD_ACTIVE ) && !(m_iHideHUDDisplay & HIDEHUD_ALL )) - pList->p->Draw(flTime); + pList->p->Draw( flTime ); } else { diff --git a/client/hud/hud.h b/client/hud/hud.h index ae04be8f..92fcf73f 100644 --- a/client/hud/hud.h +++ b/client/hud/hud.h @@ -591,10 +591,11 @@ private: // when the hud.txt and associated sprites are loaded. freed in ~CHud() HSPRITE *m_rghSprites; // the sprites loaded from hud.txt wrect_t *m_rgrcRects; + wrect_t nullRect; char *m_rgszSpriteNames; public: HSPRITE GetSprite( int index ) { return (index < 0) ? 0 : m_rghSprites[index]; } - wrect_t& GetSpriteRect( int index ) { return m_rgrcRects[index]; } + wrect_t& GetSpriteRect( int index ) { return (index < 0) ? nullRect : m_rgrcRects[index]; } int InitMessages( void ); // init hud messages int GetSpriteIndex( const char *SpriteName ); diff --git a/engine/client/cl_effects.c b/engine/client/cl_effects.c index 4c4eb7be..3c5cd547 100644 --- a/engine/client/cl_effects.c +++ b/engine/client/cl_effects.c @@ -226,7 +226,7 @@ void CL_AddDLights( void ) dl = cl_dlights; for( i = 0; i < MAX_DLIGHTS; i++, dl++ ) { - if( dl->radius ) re->AddDynLight( dl->origin, dl->color, dl->radius ); + if( dl->radius ) re->AddDynLight( dl->origin, dl->color, dl->radius, -1 ); } } @@ -917,7 +917,7 @@ void CL_TestEntities( void ) ================ CL_TestLights -If cl_testlights is set, create 32 lights models +if cl_testlights is set, create 32 lights models ================ */ void CL_TestLights( void ) @@ -944,7 +944,7 @@ void CL_TestLights( void ) dl.color[2] = (((i%6)+1) & 4)>>2; dl.radius = 200; - if( !re->AddDynLight( dl.origin, dl.color, dl.radius )) + if( !re->AddDynLight( dl.origin, dl.color, dl.radius, -1 )) break; } } diff --git a/engine/common/menu.c b/engine/common/menu.c index 8ac02ba6..b141ac8c 100644 --- a/engine/common/menu.c +++ b/engine/common/menu.c @@ -557,6 +557,7 @@ void PF_loadcredits( void ) if(!creditsBuffer) { +Msg( "load credits\n" ); // load credits if needed creditsBuffer = FS_LoadFile( s, &count ); if( count ) diff --git a/engine/engine.plg b/engine/engine.plg new file mode 100644 index 00000000..45d2c2f7 --- /dev/null +++ b/engine/engine.plg @@ -0,0 +1,16 @@ + + +
+

Build Log

+

+--------------------Configuration: engine - Win32 Debug-------------------- +

+

Command Lines

+ + + +

Results

+engine.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/engine/server/server.h b/engine/server/server.h index 051d60d1..05f0792d 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -245,6 +245,7 @@ typedef struct { bool initialized; // sv_init has completed double realtime; // always increasing, no clamping, etc + double timestart; // just for profiling char mapname[CS_SIZE]; // current mapname char comment[CS_SIZE]; // map name, e.t.c. diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index b0a8916c..881e6bb3 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -513,6 +513,8 @@ void SV_PutClientInServer( edict_t *ent ) SV_LinkEdict( ent ); // m_pmatrix calculated here, so we need call this before pe->CreatePlayer ent->pvServerData->physbody = pe->CreatePlayer( ent, SV_GetModelPtr( ent ), ent->v.origin, ent->v.m_pmatrix ); Mem_EmptyPool( svgame.temppool ); // all tempstrings can be freed now + + MsgDev( D_INFO, "level loaded at %g sec\n", Sys_DoubleTime() - svs.timestart ); } /* @@ -739,10 +741,11 @@ void SV_BeginDownload_f( sv_client_t *cl ) if( !allow_download->integer || !cl->download ) { MsgDev( D_ERROR, "SV_BeginDownload_f: couldn't download %s to %s\n", name, cl->name ); - if( cl->download ) cl->download = NULL; + if( cl->download ) Mem_Free( cl->download ); MSG_WriteByte( &cl->netchan.message, svc_download ); MSG_WriteShort( &cl->netchan.message, -1 ); MSG_WriteByte( &cl->netchan.message, 0 ); + cl->download = NULL; return; } diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 45c7ac6c..217d857e 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -160,6 +160,7 @@ void SV_SpawnServer( const char *server, const char *savename ) Msg( "SpawnServer [%s]\n", server ); + svs.timestart = Sys_DoubleTime (); svs.spawncount++; // any partially connected client will be restarted sv.state = ss_dead; Host_SetServerState( sv.state ); diff --git a/launch/imagelib/imagelib.h b/launch/imagelib/imagelib.h index dec2d930..229735f9 100644 --- a/launch/imagelib/imagelib.h +++ b/launch/imagelib/imagelib.h @@ -64,9 +64,9 @@ typedef struct imglib_s const saveformat_t *saveformats; // current 2d image state - int width; - int height; - byte depth; // num layers in + word width; + word height; + word depth; // num layers in byte num_mips; // build mipmaps uint type; // main type switcher uint flags; // additional image flags @@ -499,7 +499,7 @@ extern const bpc_desc_t PFDesc[]; void Image_RoundDimensions( int *scaled_width, int *scaled_height ); byte *Image_ResampleInternal( const void *indata, int inwidth, int inheight, int outwidth, int outheight, int intype ); -byte *Image_FlipInternal( const byte *in, int *srcwidth, int *srcheight, int type, int flags ); +byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int type, int flags ); void Image_FreeImage( rgbdata_t *pack ); void Image_Save( const char *filename, rgbdata_t *pix ); size_t Image_DXTGetLinearSize( int type, int width, int height, int depth, int rgbcount ); diff --git a/launch/imagelib/img_bmp.c b/launch/imagelib/img_bmp.c index 70953e31..755d73b8 100644 --- a/launch/imagelib/img_bmp.c +++ b/launch/imagelib/img_bmp.c @@ -43,7 +43,7 @@ bool Image_LoadBMP( const char *name, const byte *buffer, size_t filesize ) // bogus file header check if( bhdr.reserved0 != 0 ) return false; - if( memcmp(bhdr.id, "BM", 2 )) + if( memcmp( bhdr.id, "BM", 2 )) { MsgDev( D_ERROR, "Image_LoadBMP: only Windows-style BMP files supported (%s)\n", name ); return false; diff --git a/launch/imagelib/img_dds.c b/launch/imagelib/img_dds.c index a14fd681..18aeaa9a 100644 --- a/launch/imagelib/img_dds.c +++ b/launch/imagelib/img_dds.c @@ -1447,7 +1447,7 @@ void Image_SetPixelFormat( int width, int height, int depth ) image.SizeOfPlane = image.bps * image.curheight; image.SizeOfData = image.SizeOfPlane * image.curdepth; - // NOTE: size of current miplevel or cubemap side, not total (filesize - sizeof(header)) + // NOTE: size of current miplevel or cubemap side, not total (filesize - sizeof( header )) image.SizeOfFile = Image_DXTGetLinearSize( image.type, width, height, depth, image.bits_count / 8 ); } @@ -2224,12 +2224,13 @@ bool Image_DecompressRGBA( uint target, int level, int intformat, uint width, ui switch( PFDesc[intformat].format ) { case PF_RGB_16: - for( i = 0, col = (color16 *)fin; i < width * height; i++, col += sizeof( color16 )) + for( i = 0, col = (color16 *)fin; i < width * height; i++ ) { fout[(i<<2)+0] = col->r << 3; fout[(i<<2)+1] = col->g << 2; fout[(i<<2)+2] = col->b << 3; fout[(i<<2)+3] = 255; + col += sizeof( color16 ); } break; case PF_RGB_24: @@ -2273,13 +2274,14 @@ bool Image_DecompressRGBA( uint target, int level, int intformat, uint width, ui void Image_DecompressDDS( const byte *buffer, uint target ) { - int i, size = 0; - int w = image.curwidth; - int h = image.curheight; - int d = image.curdepth; + int i, size = 0; + int w = image.curwidth; + int h = image.curheight; + int d = image.curdepth; // filter by cubemap side - if( image.filter != CB_HINT_NO && image.filter != target ) return; + if( image.filter != CB_HINT_NO && image.filter != target ) + return; switch( image.type ) { @@ -2315,7 +2317,7 @@ void Image_DecompressDDS( const byte *buffer, uint target ) default: Sys_Error( "Image_DecompressDDS: unknown image format\n" ); } - for( i = 0; i < image.cur_mips; i++, buffer += size ) + for( i = 0; i < image.cur_mips; i++ ) { Image_SetPixelFormat( w, h, d ); size = image.SizeOfFile; @@ -2323,6 +2325,7 @@ void Image_DecompressDDS( const byte *buffer, uint target ) if(!image.decompress( target, i, image.type, w, h, size, buffer )) break; // there were errors w = (w+1)>>1, h = (h+1)>>1, d = (d+1)>>1; // calc size of next mip + buffer += size; } } @@ -2351,7 +2354,6 @@ bool Image_ForceDecompress( void ) case PF_ATI1N: return true; // hey, how called your OpenGL extension, ATI ? case PF_ATI2N: return true; } - return false; } diff --git a/launch/imagelib/img_jpg.c b/launch/imagelib/img_jpg.c index 4e3ae0cd..34d2d75b 100644 --- a/launch/imagelib/img_jpg.c +++ b/launch/imagelib/img_jpg.c @@ -310,7 +310,7 @@ int jpeg_readmarkers( void ) void jpeg_decompress( void ) { - // decompress jpeg file (Baseline algorithm) + // decompress jpeg file (baseline algorithm) register int x, y, i, j, k, l, c; int X, Y, H, V, plane, scaleh[3], scalev[3]; static float vector[64], dct[64]; diff --git a/launch/imagelib/img_main.c b/launch/imagelib/img_main.c index 09839d44..075a6f80 100644 --- a/launch/imagelib/img_main.c +++ b/launch/imagelib/img_main.c @@ -125,7 +125,7 @@ void Image_Reset( void ) rgbdata_t *ImagePack( void ) { - rgbdata_t *pack = Mem_Alloc( Sys.imagepool, sizeof(rgbdata_t)); + rgbdata_t *pack = Mem_Alloc( Sys.imagepool, sizeof( rgbdata_t )); if( image.cubemap && image.num_sides != 6 ) { @@ -158,6 +158,7 @@ rgbdata_t *ImagePack( void ) pack->bitsCount = image.bits_count; pack->flags = image.flags; pack->palette = image.palette; + return pack; } @@ -355,7 +356,10 @@ rgbdata_t *FS_LoadImage( const char *filename, const byte *buffer, size_t size ) { com.snprintf( sidename, MAX_STRING, "%s%s.%s", loadname, cmap->type[i].suf, format->ext ); if( FS_AddSideToPack( sidename, cmap->type[i].flags )) // process flags to flip some sides + { + Mem_Free( f ); break; // loaded + } } Mem_Free( f ); } diff --git a/launch/imagelib/img_pcx.c b/launch/imagelib/img_pcx.c index 70ceed03..dcdccd24 100644 --- a/launch/imagelib/img_pcx.c +++ b/launch/imagelib/img_pcx.c @@ -62,12 +62,12 @@ bool Image_LoadPCX( const char *name, const byte *buffer, size_t filesize ) for (x = 0; x < image.width && fin < enddata;) { dataByte = *fin++; - if(dataByte >= 0xC0) + if( dataByte >= 0xC0 ) { - if (fin >= enddata) break; + if( fin >= enddata ) break; x2 = x + (dataByte & 0x3F); dataByte = *fin++; - if (x2 > image.width) x2 = image.width; // technically an error + if( x2 > image.width ) x2 = image.width; // technically an error while(x < x2) pix[x++] = dataByte; } else pix[x++] = dataByte; diff --git a/launch/imagelib/img_tga.c b/launch/imagelib/img_tga.c index 4b26475a..ab7e3322 100644 --- a/launch/imagelib/img_tga.c +++ b/launch/imagelib/img_tga.c @@ -12,31 +12,31 @@ Image_LoadTGA */ bool Image_LoadTGA( const char *name, const byte *buffer, size_t filesize ) { - int x, y, pix_inc, row_inc; - int red, green, blue, alpha; - int runlen, alphabits; - byte *p, *pixbuf; - const byte *fin, *enddata; - byte palette[256*4]; + int i, columns, rows, row_inc, row, col; + byte *buf_p, *pixbuf, *targa_rgba; + byte palette[256][4], red = 0, green = 0, blue = 0, alpha = 0; + int readpixelcount, pixelcount; + bool compressed; tga_t targa_header; if( filesize < sizeof( tga_t )) return false; - fin = buffer; - enddata = fin + filesize; + buf_p = (byte *)buffer; + targa_header.id_length = *buf_p++; + targa_header.colormap_type = *buf_p++; + targa_header.image_type = *buf_p++; - targa_header.id_length = *fin++; - targa_header.colormap_type = *fin++; - targa_header.image_type = *fin++; - - targa_header.colormap_index = BuffLittleShort( fin ); fin += 2; - targa_header.colormap_length = BuffLittleShort( fin ); fin += 2; - targa_header.colormap_size = *fin++; - targa_header.x_origin = BuffLittleShort( fin ); fin += 2; - targa_header.y_origin = BuffLittleShort( fin ); fin += 2; - targa_header.width = image.width = BuffLittleShort( fin ); fin += 2; - targa_header.height = image.height = BuffLittleShort( fin );fin += 2; + targa_header.colormap_index = buf_p[0] + buf_p[1] * 256; buf_p += 2; + targa_header.colormap_length = buf_p[0] + buf_p[1] * 256; buf_p += 2; + targa_header.colormap_size = *buf_p; buf_p += 1; + targa_header.x_origin = LittleShort( *((short *)buf_p )); buf_p += 2; + targa_header.y_origin = LittleShort( *((short *)buf_p )); buf_p += 2; + targa_header.width = image.width = LittleShort(*((short *)buf_p)); buf_p += 2; + targa_header.height = image.height = LittleShort(*((short *)buf_p)); buf_p += 2; + targa_header.pixel_size = *buf_p++; + targa_header.attributes = *buf_p++; + if( targa_header.id_length != 0 ) buf_p += targa_header.id_length; // skip TARGA image comment // check for tga file if(!Image_ValidSize( name )) return false; @@ -45,328 +45,155 @@ bool Image_LoadTGA( const char *name, const byte *buffer, size_t filesize ) image.num_mips = 1; image.type = PF_RGBA_32; // always exctracted to 32-bit buffer - targa_header.pixel_size = *fin++; - targa_header.attributes = *fin++; - // end of header - - // skip TARGA image comment ( usually 0 bytes ) - fin += targa_header.id_length; - - // read/skip the colormap if present (note: according to the TARGA spec it - // can be present even on truecolor or greyscale images, just not used by - // the image data) - if( targa_header.colormap_type ) + if( targa_header.image_type == 1 || targa_header.image_type == 9 ) { - if( targa_header.colormap_length > 256 ) + // uncompressed colormapped image + if( targa_header.pixel_size != 8 ) { - MsgDev( D_ERROR, "Image_LoadTGA: only up to 256 colormap_length supported\n" ); + MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit images supported for type 1 and 9\n", name ); + return false; + } + if( targa_header.colormap_length != 256 ) + { + MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit colormaps are supported for type 1 and 9\n", name ); return false; } if( targa_header.colormap_index ) { - MsgDev( D_ERROR, "Image_LoadTGA: colormap_index not supported\n" ); + MsgDev( D_WARN, "Image_LoadTGA: (%s) colormap_index is not supported for type 1 and 9\n", name ); return false; } if( targa_header.colormap_size == 24 ) { - for( x = 0; x < targa_header.colormap_length; x++ ) + for( i = 0; i < targa_header.colormap_length; i++ ) { - palette[x*4+2] = *fin++; - palette[x*4+1] = *fin++; - palette[x*4+0] = *fin++; - palette[x*4+3] = 255; + palette[i][2] = *buf_p++; + palette[i][1] = *buf_p++; + palette[i][0] = *buf_p++; + palette[i][3] = 255; } } else if( targa_header.colormap_size == 32 ) { - for( x = 0; x < targa_header.colormap_length; x++ ) + for( i = 0; i < targa_header.colormap_length; i++ ) { - palette[x*4+2] = *fin++; - palette[x*4+1] = *fin++; - palette[x*4+0] = *fin++; - palette[x*4+3] = *fin++; + palette[i][2] = *buf_p++; + palette[i][1] = *buf_p++; + palette[i][0] = *buf_p++; + palette[i][3] = *buf_p++; } } else { - Msg("Image_LoadTGA: Only 32 and 24 bit colormap_size supported\n"); + MsgDev( D_WARN, "Image_LoadTGA: (%s) only 24 and 32 bit colormaps are supported for type 1 and 9\n", name ); return false; } } - - // check our pixel_size restrictions according to image_type - switch (targa_header.image_type & ~8) + else if( targa_header.image_type == 2 || targa_header.image_type == 10 ) { - case 2: - if( targa_header.pixel_size != 24 && targa_header.pixel_size != 32 ) + // uncompressed or RLE compressed RGB + if( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) { - MsgDev(D_ERROR, "LoadTGA: (%s) have unsupported pixel size '%d', for type '%d'\n", name, targa_header.pixel_size, targa_header.image_type ); + MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 32 or 24 bit images supported for type 2 and 10\n", name ); return false; } - break; - case 3: - // set up a palette to make the loader easier - for( x = 0; x < 256; x++ ) - { - palette[x*4+2] = x; - palette[x*4+1] = x; - palette[x*4+0] = x; - palette[x*4+3] = 255; - } - // fall through to colormap case - case 1: + } + else if( targa_header.image_type == 3 || targa_header.image_type == 11 ) + { + // uncompressed greyscale if( targa_header.pixel_size != 8 ) { - MsgDev( D_ERROR, "Image_LoadTGA: only 8bit pixel size for type 1, 3, 9, and 11 images supported\n" ); + MsgDev( D_WARN, "Image_LoadTGA: (%s) Only 8 bit images supported for type 3 and 11\n", name ); return false; } - break; - default: - MsgDev(D_ERROR, "Image_LoadTGA: (%s) is unsupported image type '%i'\n", name, targa_header.image_type ); - return false; } - if( targa_header.attributes & 0x10 ) - { - MsgDev( D_WARN, "Image_LoadTGA: (%s): top right and bottom right origin are not supported\n", name ); - return false; - } + columns = targa_header.width; + rows = targa_header.height; - // number of attribute bits per pixel, we only support 0 or 8 - alphabits = targa_header.attributes & 0x0F; - if( alphabits != 8 && alphabits != 0 ) - { - MsgDev( D_WARN, "LoadTGA: (%s) have invalid attributes '%i'\n", name, alphabits ); - return false; - } - - image.flags |= alphabits ? IMAGE_HAS_ALPHA : 0; image.size = image.width * image.height * 4; - image.rgba = Mem_Alloc( Sys.imagepool, image.size ); + targa_rgba = image.rgba = Mem_Alloc( Sys.imagepool, image.size ); - // If bit 5 of attributes isn't set, the image has been stored from bottom to top - if(!(targa_header.attributes & 0x20)) + // if bit 5 of attributes isn't set, the image has been stored from bottom to top + if( targa_header.attributes & 0x20 ) { - pixbuf = image.rgba + (image.height - 1) * image.width * 4; - row_inc = -image.width * 4 * 2; + pixbuf = targa_rgba; + row_inc = 0; } else { - pixbuf = image.rgba; - row_inc = 0; + pixbuf = targa_rgba + ( rows - 1 ) * columns * 4; + row_inc = -columns * 4 * 2; } - x = y = 0; - red = green = blue = alpha = 255; - pix_inc = 1; - if((targa_header.image_type & ~8) == 2) pix_inc = targa_header.pixel_size / 8; - - switch( targa_header.image_type ) + compressed = ( targa_header.image_type == 9 || targa_header.image_type == 10 || targa_header.image_type == 11 ); + for( row = col = 0; row < rows; ) { - case 1: // colormapped, uncompressed - case 3: // greyscale, uncompressed - if( fin + image.width * image.height * pix_inc > enddata ) - break; - for( y = 0; y < image.height; y++, pixbuf += row_inc ) - { - for( x = 0; x < image.width; x++ ) - { - p = palette + *fin++ * 4; - *pixbuf++ = p[0]; - *pixbuf++ = p[1]; - *pixbuf++ = p[2]; - *pixbuf++ = p[3]; - } - } - break; - case 2: - // BGR or BGRA, uncompressed - if( fin + image.width * image.height * pix_inc > enddata ) - break; - if( targa_header.pixel_size == 32 && alphabits ) - { - for( y = 0;y < image.height;y++, pixbuf += row_inc ) - { - for( x = 0;x < image.width;x++, fin += pix_inc ) - { - *pixbuf++ = fin[2]; - *pixbuf++ = fin[1]; - *pixbuf++ = fin[0]; - *pixbuf++ = fin[3]; + pixelcount = 0x10000; + readpixelcount = 0x10000; - if( fin[2] != fin[1] || fin[1] != fin[0] ) - image.flags |= IMAGE_HAS_COLOR; - } - } - } - else // 24 bits + if( compressed ) { - for( y = 0; y < image.height; y++, pixbuf += row_inc ) - { - for( x = 0;x < image.width; x++, fin += pix_inc ) - { - *pixbuf++ = fin[2]; - *pixbuf++ = fin[1]; - *pixbuf++ = fin[0]; - *pixbuf++ = 255; - - if( fin[2] != fin[1] || fin[1] != fin[0] ) - image.flags |= IMAGE_HAS_COLOR; - } - } + pixelcount = *buf_p++; + if( pixelcount & 0x80 ) // run-length packet + readpixelcount = 1; + pixelcount = 1 + ( pixelcount & 0x7f ); } - break; - case 9: // colormapped, RLE - case 11: // greyscale, RLE - for( y = 0; y < image.height; y++, pixbuf += row_inc ) + + while( pixelcount-- && ( row < rows ) ) { - for( x = 0; x < image.width; ) + if( readpixelcount-- > 0 ) { - if( fin >= enddata ) break; // error - truncated file - runlen = *fin++; - if( runlen & 0x80 ) + switch( targa_header.image_type ) { - // RLE - all pixels the same color - runlen += 1 - 0x80; - if( fin + pix_inc > enddata ) - break; // error - truncated file - if( x + runlen > image.width ) - break; // error - line exceeds width - p = palette + *fin++ * 4; - red = p[0]; - green = p[1]; - blue = p[2]; - alpha = p[3]; - for( ; runlen--; x++ ) + case 1: + case 9: + // colormapped image + blue = *buf_p++; + red = palette[blue][0]; + green = palette[blue][1]; + alpha = palette[blue][3]; + blue = palette[blue][2]; + if( alpha != 255 ) image.flags |= IMAGE_HAS_ALPHA; + break; + case 2: + case 10: + // 24 or 32 bit image + blue = *buf_p++; + green = *buf_p++; + red = *buf_p++; + alpha = 255; + if( targa_header.pixel_size == 32 ) { - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alpha; - } - } - else - { - // uncompressed - all pixels different color - runlen++; - if( fin + pix_inc * runlen > enddata ) - break; // error - truncated file - if( x + runlen > image.width ) - break; // error - line exceeds width - for( ; runlen--; x++ ) - { - p = palette + *fin++ * 4; - *pixbuf++ = p[0]; - *pixbuf++ = p[1]; - *pixbuf++ = p[2]; - *pixbuf++ = p[3]; - - if( p[0] != p[1] || p[1] != p[2] ) - image.flags |= IMAGE_HAS_COLOR; + alpha = *buf_p++; + if( alpha != 255 ) + image.flags |= IMAGE_HAS_ALPHA; } + break; + case 3: + case 11: + // greyscale image + blue = green = red = *buf_p++; + alpha = 255; + break; } } - } - break; - case 10: - // BGR or BGRA, RLE - if( targa_header.pixel_size == 32 && alphabits ) - { - for( y = 0; y < image.height; y++, pixbuf += row_inc ) - { - for (x = 0; x < image.width; ) - { - if( fin >= enddata ) break; // error - truncated file - runlen = *fin++; - if( runlen & 0x80 ) - { - // RLE - all pixels the same color - runlen += 1 - 0x80; - if( fin + pix_inc > enddata ) break; // error - truncated file - if( x + runlen > image.width) break; // error - line exceeds width - red = fin[2]; - green = fin[1]; - blue = fin[0]; - alpha = fin[3]; - fin += pix_inc; - for( ; runlen--; x++) - { - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alpha; - } - } - else - { - // uncompressed - all pixels different color - runlen++; - if( fin + pix_inc * runlen > enddata ) break; // error - truncated file - if( x + runlen > image.width ) break; // error - line exceeds width - for( ;runlen--; x++, fin += pix_inc ) - { - *pixbuf++ = fin[2]; - *pixbuf++ = fin[1]; - *pixbuf++ = fin[0]; - *pixbuf++ = fin[3]; - if( fin[2] != fin[1] || fin[1] != fin[0] ) - image.flags |= IMAGE_HAS_COLOR; - } - } - } + if( red != green || green != blue ) + image.flags |= IMAGE_HAS_COLOR; + + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = alpha; + if( ++col == columns ) + { + // run spans across rows + row++; + col = 0; + pixbuf += row_inc; } } - else - { - for( y = 0; y < image.height; y++, pixbuf += row_inc ) - { - for (x = 0; x < image.width; ) - { - if( fin >= enddata ) break; // error - truncated file - runlen = *fin++; - if( runlen & 0x80 ) - { - // RLE - all pixels the same color - runlen += 1 - 0x80; - if( fin + pix_inc > enddata ) break; // error - truncated file - if( x + runlen > image.width )break; // error - line exceeds width - red = fin[2]; - green = fin[1]; - blue = fin[0]; - alpha = 255; - fin += pix_inc; - for( ;runlen--; x++ ) - { - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alpha; - } - } - else - { - // uncompressed - all pixels different color - runlen++; - if( fin + pix_inc * runlen > enddata ) break; // error - truncated file - if( x + runlen > image.width ) break; // error - line exceeds width - for ( ; runlen--; x++, fin += pix_inc) - { - *pixbuf++ = fin[2]; - *pixbuf++ = fin[1]; - *pixbuf++ = fin[0]; - *pixbuf++ = 255; - - if( fin[2] != fin[1] || fin[1] != fin[0] ) - image.flags |= IMAGE_HAS_COLOR; - } - } - } - } - } - break; - // unknown image_type - default: return false; } return true; } diff --git a/launch/imagelib/img_utils.c b/launch/imagelib/img_utils.c index 1f2829cc..866667b9 100644 --- a/launch/imagelib/img_utils.c +++ b/launch/imagelib/img_utils.c @@ -615,12 +615,12 @@ bool Image_Copy8bitRGBA( const byte *in, byte *out, int pixels ) if( !image.d_currentpal ) { - MsgDev(D_ERROR,"Image_Copy8bitRGBA: no palette set\n"); + MsgDev( D_ERROR, "Image_Copy8bitRGBA: no palette set\n" ); return false; } if( !in ) { - MsgDev(D_ERROR,"Image_Copy8bitRGBA: no input image\n"); + MsgDev( D_ERROR, "Image_Copy8bitRGBA: no input image\n" ); return false; } @@ -1181,11 +1181,11 @@ byte *Image_FloodInternal( const byte *indata, int inwidth, int inheight, int ou Image_Flip ================ */ -byte *Image_FlipInternal( const byte *in, int *srcwidth, int *srcheight, int type, int flags ) +byte *Image_FlipInternal( const byte *in, word *srcwidth, word *srcheight, int type, int flags ) { int i, x, y; - int width = *srcwidth; - int height = *srcheight; + word width = *srcwidth; + word height = *srcheight; int samples = PFDesc[type].bpp; bool flip_x = ( flags & IMAGE_FLIP_X ) ? true : false; bool flip_y = ( flags & IMAGE_FLIP_Y ) ? true : false; @@ -1290,6 +1290,7 @@ rgbdata_t *Image_DecompressInternal( rgbdata_t *pic ) case PF_RGBA_GN: case PF_RGBA_32: case PF_ABGR_128F: + pic->type = PF_RGBA_32; return pic; // just change type } @@ -1303,15 +1304,17 @@ rgbdata_t *Image_DecompressInternal( rgbdata_t *pic ) image.num_mips = 0; // clear mipcount buf = image.rgba; - for( i = 0, offset = 0; i < numsides; i++, buf += offset ) + for( i = 0, offset = 0; i < numsides; i++ ) { Image_SetPixelFormat( image.curwidth, image.curheight, image.curdepth ); offset = image.SizeOfFile; // move pointer Image_DecompressDDS( buf, target + i ); + buf += offset; } // now we can change type to RGBA - if( image.filter != CB_HINT_NO ) image.flags &= ~IMAGE_CUBEMAP; // side extracted + if( image.filter != CB_HINT_NO ) + image.flags &= ~IMAGE_CUBEMAP; // side extracted image.type = PF_RGBA_32; FS_FreeImage( pic ); // free original diff --git a/launch/imagelib/img_vtf.c b/launch/imagelib/img_vtf.c index 838805f2..5edbcb71 100644 --- a/launch/imagelib/img_vtf.c +++ b/launch/imagelib/img_vtf.c @@ -111,7 +111,7 @@ size_t Image_VTFCalcMipmapSize( vtf_t *hdr, int mipNum ) ================ Image_VTFCalcImageSize -main image size not included header or lowres +main image size without header and lowres ================ */ size_t Image_VTFCalcImageSize( vtf_t *hdr, bool oldformat ) @@ -201,7 +201,7 @@ void Image_VTFSwapBuffer( vtf_t *hdr, const byte *input, size_t input_size, bool Mem_Copy((byte *)input, image.tempbuffer, out_size ); if( ignore_mips ) image.num_mips = 1; if( texture ) Mem_Free( texture ); - image.size = out_size; // merge out size + image.size = out_size; // merge out size (minus envmap or identical) } /* @@ -235,7 +235,8 @@ bool Image_LoadVTF( const char *name, const byte *buffer, size_t filesize ) } i = LittleLong( vtf.ver_minor ); - if( i == VTF_SUBVERSION0 && vtf.hdr_size == 64 ) oldformat = true; // 7.0 hasn't envmap for cubemap images + if( i == VTF_SUBVERSION0 && vtf.hdr_size == 64 ) + oldformat = true; // 7.0 hasn't envmap for cubemap images // all other subversions are valid image.width = LittleShort( vtf.width ); diff --git a/launch/imagelib/img_wad.c b/launch/imagelib/img_wad.c index e9f0f19f..7832d461 100644 --- a/launch/imagelib/img_wad.c +++ b/launch/imagelib/img_wad.c @@ -154,12 +154,12 @@ bool Image_LoadWAL( const char *name, const byte *buffer, size_t filesize ) int i, flags, value, contents; // wal additional parms const byte *fin; - if( filesize < (int)sizeof(wal)) + if( filesize < (int)sizeof( wal )) { MsgDev( D_ERROR, "Image_LoadWAL: file (%s) have invalid size\n", name ); return false; } - Mem_Copy( &wal, buffer, sizeof(wal)); + Mem_Copy( &wal, buffer, sizeof( wal )); flags = LittleLong(wal.flags); value = LittleLong(wal.value); @@ -215,7 +215,7 @@ bool Image_LoadFLT( const char *name, const byte *buffer, size_t filesize ) if( Sys.app_name == HOST_NORMAL && !fs_wadsupport->integer ) return false; - if(filesize < (int)sizeof(flat)) + if(filesize < (int)sizeof( flat )) { MsgDev( D_ERROR, "Image_LoadFLAT: file (%s) have invalid size\n", name ); return false; @@ -322,7 +322,7 @@ bool Image_LoadLMP( const char *name, const byte *buffer, size_t filesize ) else { fin = (byte *)buffer; - Mem_Copy(&lmp, fin, sizeof(lmp)); + Mem_Copy( &lmp, fin, sizeof( lmp )); image.width = LittleLong( lmp.width ); image.height = LittleLong( lmp.height ); rendermode = LUMP_NORMAL; @@ -379,11 +379,11 @@ bool Image_LoadMIP( const char *name, const byte *buffer, size_t filesize ) return false; } - Mem_Copy( &mip, buffer, sizeof(mip)); - image.width = LittleLong(mip.width); - image.height = LittleLong(mip.height); + Mem_Copy( &mip, buffer, sizeof( mip )); + image.width = LittleLong( mip.width ); + image.height = LittleLong( mip.height ); if(!Image_ValidSize( name )) return false; - for(i = 0; i < 4; i++) ofs[i] = LittleLong(mip.offsets[i]); + for( i = 0; i < 4; i++ ) ofs[i] = LittleLong( mip.offsets[i] ); pixels = image.width * image.height; image.depth = 1; diff --git a/launch/launch.plg b/launch/launch.plg new file mode 100644 index 00000000..67644887 --- /dev/null +++ b/launch/launch.plg @@ -0,0 +1,64 @@ + + +
+

Build Log

+

+--------------------Configuration: launch - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp" with contents +[ +/nologo /MD /W3 /GX /O2 /I "./" /I "imagelib" /I "../public" /I "../common" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /Fo"..\temp\launch\!release/" /Fd"..\temp\launch\!release/" /FD /c +"D:\Xash3D\src_main\launch\memlib.c" +] +Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC7.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp" with contents +[ +zlib.lib png.lib user32.lib gdi32.lib advapi32.lib winmm.lib /nologo /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /out:"..\temp\launch\!release/launch.dll" /implib:"..\temp\launch\!release/launch.lib" /libpath:"./imagelib" /opt:nowin98 +"\Xash3D\src_main\temp\launch\!release\cmd.obj" +"\Xash3D\src_main\temp\launch\!release\console.obj" +"\Xash3D\src_main\temp\launch\!release\cpuinfo.obj" +"\Xash3D\src_main\temp\launch\!release\crclib.obj" +"\Xash3D\src_main\temp\launch\!release\cvar.obj" +"\Xash3D\src_main\temp\launch\!release\export.obj" +"\Xash3D\src_main\temp\launch\!release\filesystem.obj" +"\Xash3D\src_main\temp\launch\!release\img_bmp.obj" +"\Xash3D\src_main\temp\launch\!release\img_dds.obj" +"\Xash3D\src_main\temp\launch\!release\img_jpg.obj" +"\Xash3D\src_main\temp\launch\!release\img_main.obj" +"\Xash3D\src_main\temp\launch\!release\img_pcx.obj" +"\Xash3D\src_main\temp\launch\!release\img_png.obj" +"\Xash3D\src_main\temp\launch\!release\img_tga.obj" +"\Xash3D\src_main\temp\launch\!release\img_utils.obj" +"\Xash3D\src_main\temp\launch\!release\img_vtf.obj" +"\Xash3D\src_main\temp\launch\!release\img_wad.obj" +"\Xash3D\src_main\temp\launch\!release\memlib.obj" +"\Xash3D\src_main\temp\launch\!release\network.obj" +"\Xash3D\src_main\temp\launch\!release\parselib.obj" +"\Xash3D\src_main\temp\launch\!release\patch.obj" +"\Xash3D\src_main\temp\launch\!release\stdlib.obj" +"\Xash3D\src_main\temp\launch\!release\system.obj" +"\Xash3D\src_main\temp\launch\!release\utils.obj" +] +Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC8.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat" with contents +[ +@echo off +copy \Xash3D\src_main\temp\launch\!release\launch.dll "D:\Xash3D\bin\launch.dll" +] +Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPC9.bat" +Compiling... +memlib.c +Linking... + Creating library ..\temp\launch\!release/launch.lib and object ..\temp\launch\!release/launch.exp +

Output Window

+Performing Custom Build Step on \Xash3D\src_main\temp\launch\!release\launch.dll +‘Є®ЇЁа®ў ­® д ©«®ў: 1. + + + +

Results

+launch.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/launch/memlib.c b/launch/memlib.c index 937535e4..d349998e 100644 --- a/launch/memlib.c +++ b/launch/memlib.c @@ -1408,9 +1408,10 @@ void _mem_printlist( size_t minallocationsize ) Mem_Check(); Msg("memory pool list:\n"" ^3size name\n"); - for (pool = poolchain; pool; pool = pool->next) + for( pool = poolchain; pool; pool = pool->next ) { - Msg("%5luk (%5luk actual) %s (%+3li byte change)\n", (dword) ((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize ); + // poolnames can contain color symbols, make sure what color is reset + Msg( "%5luk (%5luk actual) %s (^7%+3li byte change)\n", (dword) ((pool->totalsize + 1023) / 1024), (dword)((pool->realsize + 1023) / 1024), pool->name, (long)pool->totalsize - pool->lastchecksize ); pool->lastchecksize = pool->totalsize; for( mem = pool->chain; mem; mem = mem->next ) if( mem->size >= minallocationsize ) diff --git a/physic/cm_model.c b/physic/cm_model.c index 98ff44d6..43d3523f 100644 --- a/physic/cm_model.c +++ b/physic/cm_model.c @@ -467,10 +467,16 @@ void BSP_LoadPlanes( lump_t *l ) for( i = 0; i < count; i++, in++, out++ ) { - for( j = 0; j < 3; j++ ) - out->normal[j] = LittleFloat(in->normal[j]); + out->signbits = 0; + out->type = PLANE_NONAXIAL; + + for( j = 0; j < 3; j++ ) + { + out->normal[j] = LittleFloat( in->normal[j] ); + if( out->normal[j] < 0.0f ) out->signbits |= (1<normal[j] == 1.0f ) out->type = j; + } out->dist = LittleFloat( in->dist ); - PlaneClassify( out ); // automatic plane classify } } diff --git a/public/engine_api.h b/public/engine_api.h index 7f42e118..ce16a4cf 100644 --- a/public/engine_api.h +++ b/public/engine_api.h @@ -119,24 +119,6 @@ typedef struct trace_s }; } trace_t; -_inline void PlaneClassify( cplane_t *p ) -{ - // for optimized plane comparisons - if( p->normal[0] == 1 || p->normal[0] == -1 ) - p->type = PLANE_X; - else if( p->normal[1] == 1 || p->normal[1] == -1 ) - p->type = PLANE_Y; - else if( p->normal[2] == 1 || p->normal[2] == -1 ) - p->type = PLANE_Z; - else p->type = 3; // needs alternate calc - - // for BoxOnPlaneSide - p->signbits = 0; - if( p->normal[0] < 0 ) p->signbits |= 1; - if( p->normal[1] < 0 ) p->signbits |= 2; - if( p->normal[2] < 0 ) p->signbits |= 4; -} - /* ================= CategorizePlane diff --git a/public/launch_api.h b/public/launch_api.h index 82e889f3..2ce989fb 100644 --- a/public/launch_api.h +++ b/public/launch_api.h @@ -372,12 +372,12 @@ typedef enum typedef struct rgbdata_s { - int width; // image width - int height; // image height - word depth; // multi-layer volume + word width; // image width + word height; // image height + word depth; // multi-layer volume byte numMips; // mipmap count byte bitsCount; // RGB bits count - word type; // compression type + uint type; // compression type uint flags; // misc image flags byte *palette; // palette if present byte *buffer; // image buffer diff --git a/public/qfiles_ref.h b/public/qfiles_ref.h index a38acd69..37aab199 100644 --- a/public/qfiles_ref.h +++ b/public/qfiles_ref.h @@ -586,7 +586,7 @@ typedef struct ======================================================================== */ -#define IDMD3HEADER (('3'<<24)+('P'<<16)+('D'<<8)+'I') // little-endian "IDP3" +#define ALIASMODHEADER (('3'<<24)+('P'<<16)+('D'<<8)+'I') // little-endian "IDP3" #define MD3_ALIAS_VERSION 15 #define MD3_ALIAS_MAX_LODS 4 @@ -667,119 +667,6 @@ typedef struct int ofs_end; } dmd3header_t; -/* -======================================================================== - -.SKM and .SKP models file formats - -======================================================================== -*/ - -#define SKMHEADER (('1'<<24)+('M'<<16)+('K'<<8)+'S') // little-endian "SKM1" - -#define SKM_MAX_NAME 64 -#define SKM_MAX_MESHES 32 -#define SKM_MAX_FRAMES 65536 -#define SKM_MAX_TRIS 65536 -#define SKM_MAX_VERTS (SKM_MAX_TRIS * 3) -#define SKM_MAX_BONES 256 -#define SKM_MAX_SHADERS 256 -#define SKM_MAX_FILESIZE 16777216 -#define SKM_MAX_ATTACHMENTS SKM_MAX_BONES -#define SKM_MAX_LODS 4 - -// model format related flags -#define SKM_BONEFLAG_ATTACH 1 -#define SKM_MODELTYPE 2 // (hierarchical skeletal pose) - -typedef struct -{ - char id[4]; // SKMHEADER - uint type; - uint filesize; // size of entire model file - - uint num_bones; - uint num_meshes; - - // this offset is relative to the file - uint ofs_meshes; -} dskmheader_t; - -// there may be more than one of these -typedef struct -{ - // these offsets are relative to the file - char shadername[SKM_MAX_NAME]; // name of the shader to use - char meshname[SKM_MAX_NAME]; - - uint num_verts; - uint num_tris; - uint num_references; - uint ofs_verts; - uint ofs_texcoords; - uint ofs_indices; - uint ofs_references; -} dskmmesh_t; - -// one or more of these per vertex -typedef struct -{ - float origin[3]; // vertex location (these blend) - float influence; // influence fraction (these must add up to 1) - float normal[3]; // surface normal (these blend) - uint bonenum; // number of the bone -} dskmbonevert_t; - -// variable size, parsed sequentially -typedef struct -{ - uint numweights; - // immediately followed by 1 or more ddpmbonevert_t structures - dskmbonevert_t verts[1]; -} dskmvertex_t; - -typedef struct -{ - float st[2]; -} dskmcoord_t; - -typedef struct -{ - char id[4]; // SKMHEADER - uint type; - uint filesize; // size of entire model file - - uint num_bones; - uint num_frames; - - // these offsets are relative to the file - uint ofs_bones; - uint ofs_frames; -} dskpheader_t; - -// one per bone -typedef struct -{ - // name examples: upperleftarm leftfinger1 leftfinger2 hand, etc - char name[SKM_MAX_NAME]; - signed int parent; // parent bone number - uint flags; // flags for the bone -} dskpbone_t; - -typedef struct -{ - float quat[4]; - float origin[3]; -} dskpbonepose_t; - -// immediately followed by bone positions for the frame -typedef struct -{ - // name examples: idle_1 idle_2 idle_3 shoot_1 shoot_2 shoot_3, etc - char name[SKM_MAX_NAME]; - uint ofs_bonepositions; -} dskpframe_t; - /* ============================================================================== SAVE FILE diff --git a/public/render_api.h b/public/render_api.h index 4df290fe..1d16c543 100644 --- a/public/render_api.h +++ b/public/render_api.h @@ -70,7 +70,7 @@ typedef struct render_exp_s // prepare frame to rendering bool (*AddRefEntity)( edict_t *pRefEntity, int ed_type, float lerp ); - bool (*AddDynLight)( vec3_t org, vec3_t color, float intensity ); + bool (*AddDynLight)( vec3_t org, vec3_t color, float intensity, shader_t shader ); bool (*AddPolygon)( const poly_t *poly ); bool (*AddLightStyle)( int stylenum, vec3_t color ); void (*ClearScene)( void ); diff --git a/render/r_alias.c b/render/r_alias.c index 11149291..fd458d3c 100644 --- a/render/r_alias.c +++ b/render/r_alias.c @@ -72,279 +72,6 @@ static void Mod_AliasBuildMeshesForFrame0( ref_model_t *mod ) } } - -#ifdef QUAKE2_JUNK - -/* -============================================================================== - -MD2 MODELS - -============================================================================== -*/ - -/* -================= -Mod_AliasCalculateVertexNormals -================= -*/ -static void Mod_AliasCalculateVertexNormals( int numElems, elem_t *elems, int numVerts, maliasvertex_t *v ) -{ - int i, j, k, vertRemap[MD2_MAX_VERTS]; - vec3_t dir1, dir2, normal, trnormals[MD2_MAX_TRIANGLES]; - int numUniqueVerts, uniqueVerts[MD2_MAX_VERTS]; - byte latlongs[MD2_MAX_VERTS][2]; - - // count unique verts - for( i = 0, numUniqueVerts = 0; i < numVerts; i++ ) - { - for( j = 0; j < numUniqueVerts; j++ ) - { - if( VectorCompare( v[uniqueVerts[j]].point, v[i].point ) ) - { - vertRemap[i] = j; - break; - } - } - - if( j == numUniqueVerts ) - { - vertRemap[i] = numUniqueVerts; - uniqueVerts[numUniqueVerts++] = i; - } - } - - for( i = 0, j = 0; i < numElems; i += 3, j++ ) - { - // calculate two mostly perpendicular edge directions - VectorSubtract( v[elems[i+0]].point, v[elems[i+1]].point, dir1 ); - VectorSubtract( v[elems[i+2]].point, v[elems[i+1]].point, dir2 ); - - // we have two edge directions, we can calculate a third vector from - // them, which is the direction of the surface normal - CrossProduct( dir1, dir2, trnormals[j] ); - VectorNormalize( trnormals[j] ); - } - - // sum all triangle normals - for( i = 0; i < numUniqueVerts; i++ ) - { - VectorClear( normal ); - - for( j = 0, k = 0; j < numElems; j += 3, k++ ) - { - if( vertRemap[elems[j+0]] == i || vertRemap[elems[j+1]] == i || vertRemap[elems[j+2]] == i ) - VectorAdd( normal, trnormals[k], normal ); - } - - VectorNormalize( normal ); - NormToLatLong( normal, latlongs[i] ); - } - - // copy normals back - for( i = 0; i < numVerts; i++ ) - *(short *)v[i].latlong = *(short *)latlongs[vertRemap[i]]; -} - -/* -================= -Mod_LoadAliasMD2Model -================= -*/ -void Mod_LoadAliasMD2Model( ref_model_t *mod, ref_model_t *parent, void *buffer ) -{ - int i, j, k; - int version, framesize; - float skinwidth, skinheight; - int numverts, numelems; - int indremap[MD2_MAX_TRIANGLES*3]; - elem_t ptempelem[MD2_MAX_TRIANGLES*3], ptempstelem[MD2_MAX_TRIANGLES*3]; - dmd2_t *pinmodel; - dstvert_t *pinst; - dtriangle_t *pintri; - daliasframe_t *pinframe; - elem_t *poutelem; - maliasmodel_t *poutmodel; - maliasmesh_t *poutmesh; - vec2_t *poutcoord; - maliasframe_t *poutframe; - maliasvertex_t *poutvertex; - maliasskin_t *poutskin; - - pinmodel = ( dmd2_t * )buffer; - version = LittleLong( pinmodel->version ); - framesize = LittleLong( pinmodel->framesize ); - - if( version != MD2_ALIAS_VERSION ) - Host_Error( ERR_DROP, "%s has wrong version number (%i should be %i)", - mod->name, version, MD2_ALIAS_VERSION ); - - mod->type = mod_alias; - mod->aliasmodel = poutmodel = Mod_Malloc( mod, sizeof( maliasmodel_t ) ); - mod->radius = 0; - ClearBounds( mod->mins, mod->maxs ); - - // byte swap the header fields and sanity check - skinwidth = LittleLong( pinmodel->skinwidth ); - skinheight = LittleLong( pinmodel->skinheight ); - - if( skinwidth <= 0 ) - Host_Error( ERR_DROP, "model %s has invalid skin width", mod->name ); - if( skinheight <= 0 ) - Host_Error( ERR_DROP, "model %s has invalid skin height", mod->name ); - - poutmodel->numframes = LittleLong( pinmodel->num_frames ); - poutmodel->numskins = LittleLong( pinmodel->num_skins ); - - if( poutmodel->numframes > MD2_MAX_FRAMES ) - Host_Error( ERR_DROP, "model %s has too many frames", mod->name ); - else if( poutmodel->numframes <= 0 ) - Host_Error( ERR_DROP, "model %s has no frames", mod->name ); - if( poutmodel->numskins > MD2_MAX_SKINS ) - Host_Error( ERR_DROP, "model %s has too many skins", mod->name ); - else if( poutmodel->numskins < 0 ) - Host_Error( ERR_DROP, "model %s has invalid number of skins", mod->name ); - - poutmodel->numtags = 0; - poutmodel->tags = NULL; - poutmodel->nummeshes = 1; - - poutmesh = poutmodel->meshes = Mod_Malloc( mod, sizeof( maliasmesh_t ) ); - Q_strncpyz( poutmesh->name, "default", MD3_MAX_PATH ); - - poutmesh->numverts = LittleLong( pinmodel->num_xyz ); - poutmesh->numtris = LittleLong( pinmodel->num_tris ); - - if( poutmesh->numverts <= 0 ) - Host_Error( "model %s has no vertices\n", mod->name ); - else if( poutmesh->numverts > MD2_MAX_VERTS ) - Host_Error( "model %s has too many vertices\n", mod->name ); - if( poutmesh->numtris > MD2_MAX_TRIANGLES ) - Host_Error( "model %s has too many triangles\n", mod->name ); - else if( poutmesh->numtris <= 0 ) - Host_Error( "model %s has no triangles\n", mod->name ); - - numelems = poutmesh->numtris * 3; - poutelem = poutmesh->elems = Mod_Malloc( mod, numelems * sizeof( elem_t ) ); - - // - // load triangle lists - // - pintri = ( dtriangle_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_tris ) ); - pinst = ( dstvert_t * ) ( ( byte * )pinmodel + LittleLong( pinmodel->ofs_st ) ); - - for( i = 0, k = 0; i < poutmesh->numtris; i++, k += 3 ) - { - for( j = 0; j < 3; j++ ) - { - ptempelem[k+j] = ( elem_t )LittleShort( pintri[i].index_xyz[j] ); - ptempstelem[k+j] = ( elem_t )LittleShort( pintri[i].index_st[j] ); - } - } - - // - // build list of unique vertexes - // - numverts = 0; - memset( indremap, -1, MD2_MAX_TRIANGLES * 3 * sizeof( int ) ); - - for( i = 0; i < numelems; i++ ) - { - if( indremap[i] != -1 ) - continue; - - // remap duplicates - for( j = i + 1; j < numelems; j++ ) - { - if( ( ptempelem[j] == ptempelem[i] ) - && ( pinst[ptempstelem[j]].s == pinst[ptempstelem[i]].s ) - && ( pinst[ptempstelem[j]].t == pinst[ptempstelem[i]].t ) ) - { - indremap[j] = i; - poutelem[j] = numverts; - } - } - - // add unique vertex - indremap[i] = i; - poutelem[i] = numverts++; - } - - MsgDev( "%s: remapped %i verts to %i (%i tris)\n", mod->name, poutmesh->numverts, numverts, poutmesh->numtris ); - - poutmesh->numverts = numverts; - - // - // load base s and t vertices - // - poutcoord = poutmesh->stArray = Mod_Malloc( mod, numverts * sizeof( vec2_t ) ); - - for( i = 0; i < numelems; i++ ) - { - if( indremap[i] == i ) - { - poutcoord[poutelem[i]][0] = ( (float)LittleShort( pinst[ptempstelem[i]].s ) + 0.5 ) / skinwidth; - poutcoord[poutelem[i]][1] = ( (float)LittleShort( pinst[ptempstelem[i]].t ) + 0.5 ) / skinheight; - } - } - - // - // load the frames - // - poutframe = poutmodel->frames = Mod_Malloc( mod, poutmodel->numframes * ( sizeof( maliasframe_t ) + numverts * sizeof( maliasvertex_t ) ) ); - poutvertex = poutmesh->vertexes = ( maliasvertex_t *)( ( byte * )poutframe + poutmodel->numframes * sizeof( maliasframe_t ) ); - - for( i = 0; i < poutmodel->numframes; i++, poutframe++, poutvertex += numverts ) - { - pinframe = ( daliasframe_t * )( ( byte * )pinmodel + LittleLong( pinmodel->ofs_frames ) + i * framesize ); - - for( j = 0; j < 3; j++ ) - { - poutframe->scale[j] = LittleFloat( pinframe->scale[j] ); - poutframe->translate[j] = LittleFloat( pinframe->translate[j] ); - } - - for( j = 0; j < numelems; j++ ) - { // verts are all 8 bit, so no swapping needed - if( indremap[j] == j ) - { - poutvertex[poutelem[j]].point[0] = (short)pinframe->verts[ptempelem[j]].v[0]; - poutvertex[poutelem[j]].point[1] = (short)pinframe->verts[ptempelem[j]].v[1]; - poutvertex[poutelem[j]].point[2] = (short)pinframe->verts[ptempelem[j]].v[2]; - } - } - - Mod_AliasCalculateVertexNormals( numelems, poutelem, numverts, poutvertex ); - - VectorCopy( poutframe->translate, poutframe->mins ); - VectorMA( poutframe->translate, 255, poutframe->scale, poutframe->maxs ); - poutframe->radius = RadiusFromBounds( poutframe->mins, poutframe->maxs ); - - mod->radius = max( mod->radius, poutframe->radius ); - AddPointToBounds( poutframe->mins, mod->mins, mod->maxs ); - AddPointToBounds( poutframe->maxs, mod->mins, mod->maxs ); - } - - // - // build S and T vectors for frame 0 - // - Mod_AliasBuildMeshesForFrame0( mod ); - - - // register all skins - poutskin = poutmodel->skins = Mod_Malloc( mod, poutmodel->numskins * sizeof( maliasskin_t ) ); - - for( i = 0; i < poutmodel->numskins; i++, poutskin++ ) - { - if( LittleLong( pinmodel->ofs_skins ) == -1 ) - continue; - poutskin->shader = R_RegisterSkin( ( char * )pinmodel + LittleLong( pinmodel->ofs_skins ) + i*MD2_MAX_SKINNAME ); - } - mod->touchFrame = tr.registration_sequence; // register model -} - -#endif - /* ============================================================================== @@ -469,9 +196,9 @@ void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *b poutmesh = poutmodel->meshes = ( maliasmesh_t * )buf; for( i = 0; i < poutmodel->nummeshes; i++, poutmesh++ ) { - if( pinmesh->id != IDMD3HEADER ) + if( pinmesh->id != ALIASMODHEADER ) Host_Error( "mesh %s in model %s has wrong id (%s should be %s)\n", - pinmesh->name, mod->name, pinmesh->id, IDMD3HEADER ); + pinmesh->name, mod->name, pinmesh->id, ALIASMODHEADER ); com.strncpy( poutmesh->name, pinmesh->name, MD3_MAX_PATH ); @@ -505,7 +232,8 @@ void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *b poutskin = poutmesh->skins = ( maliasskin_t * )buf; buf += sizeof( maliasskin_t ) * poutmesh->numskins; for( j = 0; j < poutmesh->numskins; j++, pinskin++, poutskin++ ) { - poutskin->shader = R_RegisterSkin( pinskin->name ); + FS_StripExtension( pinskin->name ); + poutskin->shader = R_LoadShader( pinskin->name, SHADER_ALIAS, false, 0, SHADER_INVALID ); R_DeformvBBoxForShader( poutskin->shader, ebbox ); } @@ -1006,10 +734,6 @@ bool R_CullAliasModel( ref_entity_t *e ) shader = R_FindShaderForSkinFile( e->customSkin, mesh->name ); else if( e->customShader ) shader = e->customShader; -#ifdef QUAKE2_JUNK - else if( ( e->skinNum >= 0 ) && ( e->skinNum < aliasmodel->numskins ) ) - shader = aliasmodel->skins[e->skinNum].shader; -#endif else if( mesh->numskins ) { for( j = 0; j < mesh->numskins; j++ ) @@ -1089,10 +813,6 @@ void R_AddAliasModelToList( ref_entity_t *e ) shader = R_FindShaderForSkinFile( e->customSkin, mesh->name ); else if( e->customShader ) shader = e->customShader; -#ifdef QUAKE2_JUNK - else if( ( e->skinNum >= 0 ) && ( e->skinNum < aliasmodel->numskins ) ) - shader = aliasmodel->skins[e->skinNum].shader; -#endif else if( mesh->numskins ) { for( j = 0; j < mesh->numskins; j++ ) diff --git a/render/r_backend.c b/render/r_backend.c index 651b24c4..a1777124 100644 --- a/render/r_backend.c +++ b/render/r_backend.c @@ -22,22 +22,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mathlib.h" #include "quatlib.h" -#define FTABLE_SIZE_POW 10 -#define FTABLE_SIZE ( 1<pointer ); + + if( r_features & MF_ENABLENORMALS ) { - pglVertexPointer( 3, GL_FLOAT, 16, vertsArray ); - - if( r_features & MF_ENABLENORMALS ) - { - r_normalsEnabled = true; - pglEnableClientState( GL_NORMAL_ARRAY ); - pglNormalPointer( GL_FLOAT, 16, normalsArray ); - } + r_normalsEnabled = true; + R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t )); + pglEnableClientState( GL_NORMAL_ARRAY ); + pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer ); } if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT )) @@ -509,16 +508,15 @@ void R_FlushArrays( void ) else if( r_backacc.numColors > 1 ) { pglEnableClientState( GL_COLOR_ARRAY ); - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, colorArray ); + R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t )); + pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer ); } if( r_drawelements->integer || glState.in2DMode || RI.refdef.rdflags & RDF_NOWORLDMODEL ) { if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - else - pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); + else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); } if( r_backacc.numColors > 1 ) @@ -934,22 +932,15 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix ) case TCGEN_BASE: GL_DisableAllTexGens(); - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - pglTexCoordPointer( 2, GL_FLOAT, 0, coordsArray ); - return true; - } - break; + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); + return true; case TCGEN_LIGHTMAP: GL_DisableAllTexGens(); - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - pglTexCoordPointer( 2, GL_FLOAT, 0, lightmapCoordsArray[r_lightmapStyleNum[unit]] ); - return true; - } - break; - + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray[r_lightmapStyleNum[unit]], r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); + return true; case TCGEN_ENVIRONMENT: { float depth, *n; @@ -977,12 +968,9 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix ) GL_DisableAllTexGens(); - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] ); - return true; - } - break; + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); + return true; } case TCGEN_VECTOR: @@ -1143,34 +1131,23 @@ static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix ) GL_DisableAllTexGens(); - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] ); - return false; - } - break; + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); + return false; } case TCGEN_SVECTORS: GL_DisableAllTexGens(); - - if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) - { - pglTexCoordPointer( 4, GL_FLOAT, 0, sVectorsArray ); - return true; - } - break; - + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t )); + pglTexCoordPointer( 4, GL_FLOAT, 0, tr.tcoordBuffer[unit]->pointer ); + return true; case TCGEN_PROJECTION_SHADOW: GL_SetTexCoordArrayMode( 0 ); GL_DisableAllTexGens(); Matrix4_Multiply( r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix, matrix ); break; - - default: - break; + default: break; } - return identityMatrix; } @@ -1268,9 +1245,8 @@ static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit tex = R_ShaderpassTex( pass, unit ); GL_Bind( unit, tex ); - if( unit && !pass->program ) - pglEnable( GL_TEXTURE_2D ); - GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY ) ); + if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D ); + GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY )); identityMatrix = R_VertexTCBase( pass, unit, result ); @@ -2805,8 +2781,7 @@ static void R_DrawTriangles( void ) if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); - else - pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); + else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); } /* @@ -2825,9 +2800,7 @@ static void R_DrawNormals( void ) for( i = 0; i < r_backacc.numVerts; i++ ) { pglVertex3fv( vertsArray[i] ); - pglVertex3f( vertsArray[i][0] + normalsArray[i][0], - vertsArray[i][1] + normalsArray[i][1], - vertsArray[i][2] + normalsArray[i][2] ); + pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] ); } pglEnd(); } diff --git a/render/r_backend.h b/render/r_backend.h index 2ce82e5d..ec5bc3ba 100644 --- a/render/r_backend.h +++ b/render/r_backend.h @@ -31,9 +31,7 @@ enum VBO_VERTS, VBO_NORMALS, VBO_COLORS, -// VBO_INDEXES, VBO_TC0, - VBO_ENDMARKER }; @@ -55,24 +53,27 @@ extern vec4_t *sVectorsArray; extern vec2_t *coordsArray; extern vec2_t *lightmapCoordsArray[LM_STYLES]; extern rgba_t colorArray[MAX_ARRAY_VERTS]; - -extern int r_numVertexBufferObjects; -extern GLuint r_vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS]; - extern int r_features; //=================================================================== +typedef struct ref_buffer_s +{ + byte *pointer; + int size; + uint usage; + uint bufNum; +} ref_buffer_t; typedef struct { - uint numVerts; - uint numElems; - uint numColors; + uint numVerts; + uint numElems; + uint numColors; - uint c_totalVerts; - uint c_totalTris; - uint c_totalFlushes; - uint c_totalKeptLocks; + uint c_totalVerts; + uint c_totalTris; + uint c_totalFlushes; + uint c_totalKeptLocks; } ref_backacc_t; typedef struct @@ -80,6 +81,14 @@ typedef struct // renderer global variables int registration_sequence; + // vbo stuff + int numVertexBufferObjects; + ref_buffer_t vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS]; + ref_buffer_t *vertexBuffer; + ref_buffer_t *normalBuffer; + ref_buffer_t *colorsBuffer; + ref_buffer_t *tcoordBuffer[MAX_TEXTURE_UNITS]; + // builtin textures texture_t *cinTexture; // cinematic texture texture_t *portaltexture1; // portal view @@ -98,6 +107,7 @@ typedef struct texture_t *lightmapTextures[MAX_TEXTURES]; // builtin shaders + ref_shader_t *defaultShader; // generic black texture } ref_globals_t; extern ref_globals_t tr; @@ -121,6 +131,11 @@ void R_BackendResetPassMask( void ); void R_DrawPhysDebug( void ); +void R_InitVertexBuffers( void ); +void R_ShutdownVertexBuffers( void ); +ref_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage ); +void R_UpdateVertexBuffer( ref_buffer_t *vertexBuffer, const void *data, size_t size ); + void R_LockArrays( int numverts ); void R_UnlockArrays( void ); void R_UnlockArrays( void ); @@ -386,14 +401,15 @@ typedef struct bool initializedMedia; int activeTMU; - GLuint *currentTextures; - GLenum *currentEnvModes; - bool *texIdentityMatrix; - int *genSTEnabled; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R - int *texCoordArrayMode; // 0 - disabled, 1 - enabled, 2 - cubemap + GLuint currentTextures[MAX_TEXTURE_UNITS]; + GLenum currentEnvModes[MAX_TEXTURE_UNITS]; + GLboolean texIdentityMatrix[MAX_TEXTURE_UNITS]; + GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R + GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap + vec4_t draw_color; - kRenderMode_t draw_rendermode; // rendermode for drawing - int draw_frame; // will be reset after each drawing + kRenderMode_t draw_rendermode; // rendermode for drawing + int draw_frame; // will be reset after each drawing int faceCull; int frontFace; diff --git a/render/r_backend.old b/render/r_backend.old new file mode 100644 index 00000000..3814a09a --- /dev/null +++ b/render/r_backend.old @@ -0,0 +1,2845 @@ +/* +Copyright (C) 2002-2007 Victor Luchits + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "r_local.h" +#include "mathlib.h" +#include "quatlib.h" + +#define FTABLE_SIZE_POW 10 +#define FTABLE_SIZE ( 1<integer ) + r_identityLighting = (int)( 255.0f / pow( 2, max( 0, floor( r_overbrightbits->value ) ) ) ); + else + r_identityLighting = 255; + + // build lookup tables + for( i = 0; i < FTABLE_SIZE; i++ ) + { + t = (float)i / (float)FTABLE_SIZE; + + r_sintable[i] = sin( t * M_PI2 ); + + if( t < 0.25 ) + r_triangletable[i] = t * 4.0; + else if( t < 0.75 ) + r_triangletable[i] = 2 - 4.0 * t; + else + r_triangletable[i] = ( t - 0.75 ) * 4.0 - 1.0; + + if( t < 0.5 ) + r_squaretable[i] = 1.0f; + else + r_squaretable[i] = -1.0f; + + r_sawtoothtable[i] = t; + r_inversesawtoothtable[i] = 1.0 - t; + } + + for( i = 0; i < 256; i++ ) + r_sintableByte[i] = sin( (float)i / 255.0 * M_PI2 ); + + // init the noise table + srand( 1001 ); + + for( i = 0; i < NOISE_SIZE; i++ ) + { + r_noisetable[i] = (float)( ( ( rand() / (float)RAND_MAX ) * 2.0 - 1.0 ) ); + r_noiseperm[i] = (unsigned char)( rand() / (float)RAND_MAX * 255 ); + } + + // init dynamic lights pass + memset( &r_dlightsPass, 0, sizeof( ref_stage_t ) ); + r_dlightsPass.flags = SHADERSTAGE_DLIGHT; + r_dlightsPass.glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ONE; + + // init fog pass + memset( &r_fogPass, 0, sizeof( ref_stage_t ) ); + r_fogPass.tcgen = TCGEN_FOG; + r_fogPass.rgbGen.type = RGBGEN_FOG; + r_fogPass.alphaGen.type = ALPHAGEN_IDENTITY; + r_fogPass.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_DECAL; + r_fogPass.glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA; + + // the very first lightmap pass is reserved for GL_REPLACE or GL_MODULATE + Mem_Set( r_lightmapPasses, 0, sizeof( r_lightmapPasses )); + r_lightmapPasses[0].rgbGen.args = r_lightmapPassesArgs[0]; + + // the rest are GL_ADD + for( i = 1; i < MAX_TEXTURE_UNITS+1; i++ ) + { + r_lightmapPasses[i].flags = SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_ADD; + r_lightmapPasses[i].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; + r_lightmapPasses[i].tcgen = TCGEN_LIGHTMAP; + r_lightmapPasses[i].alphaGen.type = ALPHAGEN_IDENTITY; + r_lightmapPasses[i].rgbGen.args = r_lightmapPassesArgs[i]; + } + + // init optional GLSL program passes + memset( r_GLSLpasses, 0, sizeof( r_GLSLpasses ) ); + r_GLSLpasses[0].flags = SHADERSTAGE_DLIGHT|SHADERSTAGE_BLEND_ADD; + r_GLSLpasses[0].glState = GLSTATE_DEPTHFUNC_EQ|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE; + + r_GLSLpasses[1].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; + r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR; + r_GLSLpasses[1].tcgen = TCGEN_BASE; + r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY; + r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY; + Mem_Copy( &r_GLSLpasses[2], &r_GLSLpasses[1], sizeof( ref_stage_t ) ); + + r_GLSLpasses[3].flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; + r_GLSLpasses[3].glState = GLSTATE_DEPTHFUNC_EQ /*|GLSTATE_OFFSET_FILL*/|GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR; + r_GLSLpasses[3].tcgen = TCGEN_PROJECTION_SHADOW; + r_GLSLpasses[3].rgbGen.type = RGBGEN_IDENTITY; + r_GLSLpasses[3].alphaGen.type = ALPHAGEN_IDENTITY; + r_GLSLpasses[3].program = DEFAULT_GLSL_SHADOWMAP_PROGRAM; + r_GLSLpasses[3].program_type = PROGRAM_TYPE_SHADOWMAP; + + Mem_Set( &r_GLSLpassOutline, 0, sizeof( r_GLSLpassOutline ) ); + r_GLSLpassOutline.flags = SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; + r_GLSLpassOutline.glState = GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO|GLSTATE_DEPTHWRITE; + r_GLSLpassOutline.rgbGen.type = RGBGEN_OUTLINE; + r_GLSLpassOutline.alphaGen.type = ALPHAGEN_OUTLINE; + r_GLSLpassOutline.tcgen = TCGEN_NONE; + r_GLSLpassOutline.program = DEFAULT_GLSL_OUTLINE_PROGRAM; + r_GLSLpassOutline.program_type = PROGRAM_TYPE_OUTLINE; +} + +/* +============== +R_BackendShutdown +============== +*/ +void R_BackendShutdown( void ) +{ + R_ShutdownVertexBuffers (); +} + +/* +============== +R_FastSin +============== +*/ +float R_FastSin( float t ) +{ + return FTABLE_EVALUATE( r_sintable, t ); +} + +/* +============= +R_LatLongToNorm +============= +*/ +void R_LatLongToNorm( const byte latlong[2], vec3_t out ) +{ + float sin_a, sin_b, cos_a, cos_b; + + cos_a = r_sintableByte[( latlong[0] + 64 ) & 255]; + sin_a = r_sintableByte[latlong[0]]; + cos_b = r_sintableByte[( latlong[1] + 64 ) & 255]; + sin_b = r_sintableByte[latlong[1]]; + + VectorSet( out, cos_b * sin_a, sin_b * sin_a, cos_a ); +} + +/* +============== +R_TableForFunc +============== +*/ +static float *R_TableForFunc( unsigned int func ) +{ + switch( func ) + { + case WAVEFORM_SIN: + return r_sintable; + case WAVEFORM_TRIANGLE: + return r_triangletable; + case WAVEFORM_SQUARE: + return r_squaretable; + case WAVEFORM_SAWTOOTH: + return r_sawtoothtable; + case WAVEFORM_INVERSESAWTOOTH: + return r_inversesawtoothtable; + + case WAVEFORM_NOISE: + return r_sintable; // default to sintable + } + + // assume error + Host_Error( "R_TableForFunc: unknown function\n" ); + + return NULL; +} + +/* +============== +R_BackendGetNoiseValue +============== +*/ +float R_BackendGetNoiseValue( float x, float y, float z, float t ) +{ + int i; + int ix, iy, iz, it; + float fx, fy, fz, ft; + float front[4], back[4]; + float fvalue, bvalue, value[2], finalvalue; + + ix = ( int )floor( x ); + fx = x - ix; + iy = ( int )floor( y ); + fy = y - iy; + iz = ( int )floor( z ); + fz = z - iz; + it = ( int )floor( t ); + ft = t - it; + + for( i = 0; i < 2; i++ ) + { + front[0] = r_noisetable[NOISE_INDEX( ix, iy, iz, it + i )]; + front[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz, it + i )]; + front[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz, it + i )]; + front[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz, it + i )]; + + back[0] = r_noisetable[NOISE_INDEX( ix, iy, iz + 1, it + i )]; + back[1] = r_noisetable[NOISE_INDEX( ix+1, iy, iz + 1, it + i )]; + back[2] = r_noisetable[NOISE_INDEX( ix, iy+1, iz + 1, it + i )]; + back[3] = r_noisetable[NOISE_INDEX( ix+1, iy+1, iz + 1, it + i )]; + + fvalue = NOISE_LERP( NOISE_LERP( front[0], front[1], fx ), NOISE_LERP( front[2], front[3], fx ), fy ); + bvalue = NOISE_LERP( NOISE_LERP( back[0], back[1], fx ), NOISE_LERP( back[2], back[3], fx ), fy ); + value[i] = NOISE_LERP( fvalue, bvalue, fz ); + } + + finalvalue = NOISE_LERP( value[0], value[1], ft ); + + return finalvalue; +} + +/* +============== +R_BackendResetCounters +============== +*/ +void R_BackendResetCounters( void ) +{ + memset( &r_backacc, 0, sizeof( r_backacc ) ); +} + +/* +============== +R_BackendStartFrame +============== +*/ +void R_BackendStartFrame( void ) +{ + r_speeds_msg[0] = '\0'; + R_BackendResetCounters(); +} + +/* +============== +R_BackendEndFrame +============== +*/ +void R_BackendEndFrame( void ) +{ + // unlock arrays if any + R_UnlockArrays(); + + // clean up texture units + R_CleanUpTextureUnits( 1 ); + + if( r_speeds->integer && !( RI.refdef.rdflags & RDF_NOWORLDMODEL ) ) + { + switch( r_speeds->integer ) + { + case 1: + default: + com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), + "%4i wpoly %4i leafs %4i verts %4i tris %4i flushes %3i locks", + c_brush_polys, + c_world_leafs, + r_backacc.c_totalVerts, + r_backacc.c_totalTris, + r_backacc.c_totalFlushes, + r_backacc.c_totalKeptLocks + ); + break; + case 2: + com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), + "lvs: %5i node: %5i farclip: %6.f", + r_mark_leaves, + r_world_node, + RI.farClip + ); + break; + case 3: + com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), + "polys\\ents: %5i\\%5i sort\\draw: %5i\\%i", + r_add_polys, r_add_entities, + r_sort_meshes, r_draw_meshes + ); + break; + case 4: + if( r_debug_surface ) + { + com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), + "%s", r_debug_surface->shader->name ); + + if( r_debug_surface->fog && r_debug_surface->fog->shader + && r_debug_surface->fog->shader != r_debug_surface->shader ) + { + com.strncat( r_speeds_msg, "\n", sizeof( r_speeds_msg ) ); + com.strncat( r_speeds_msg, r_debug_surface->fog->shader->name, sizeof( r_speeds_msg ) ); + } + } + break; + case 5: + com.snprintf( r_speeds_msg, sizeof( r_speeds_msg ), + "%.1f %.1f %.1f (%.1f,%.1f,%.1f)", + RI.refdef.vieworg[0], RI.refdef.vieworg[1], RI.refdef.vieworg[2], + RI.refdef.viewangles[0], RI.refdef.viewangles[1], RI.refdef.viewangles[2] + ); + break; + } + } +} + +/* +============== +R_LockArrays +============== +*/ +void R_LockArrays( int numverts ) +{ + if( r_arraysLocked ) return; + + R_UpdateVertexBuffer( tr.vertexBuffer, vertsArray, numverts * sizeof( vec4_t )); + pglVertexPointer( 3, GL_FLOAT, 16, tr.vertexBuffer->pointer ); + + if( r_features & MF_ENABLENORMALS ) + { + r_normalsEnabled = true; + R_UpdateVertexBuffer( tr.normalBuffer, normalsArray, numverts * sizeof( vec4_t )); + pglEnableClientState( GL_NORMAL_ARRAY ); + pglNormalPointer( GL_FLOAT, 16, tr.normalBuffer->pointer ); + } + + if( GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT )) + pglLockArraysEXT( 0, numverts ); + + r_arraysLocked = true; +} + +/* +============== +R_UnlockArrays +============== +*/ +void R_UnlockArrays( void ) +{ + if( !r_arraysLocked ) + return; + + if(GL_Support( R_CUSTOM_VERTEX_ARRAY_EXT )) + pglUnlockArraysEXT(); + + if( r_normalsEnabled ) + { + r_normalsEnabled = false; + pglDisableClientState( GL_NORMAL_ARRAY ); + } + r_arraysLocked = false; +} + +/* +============== +R_ClearArrays +============== +*/ +void R_ClearArrays( void ) +{ + int i; + + r_backacc.numVerts = 0; + r_backacc.numElems = 0; + r_backacc.numColors = 0; + + vertsArray = inVertsArray; + elemsArray = inElemsArray; + normalsArray = inNormalsArray; + sVectorsArray = inSVectorsArray; + coordsArray = inCoordsArray; + for( i = 0; i < LM_STYLES; i++ ) + lightmapCoordsArray[i] = inLightmapCoordsArray[i]; +} + +/* +============== +R_FlushArrays +============== +*/ +void R_FlushArrays( void ) +{ + if( !r_backacc.numVerts || !r_backacc.numElems ) + return; + + if( r_backacc.numColors == 1 ) + { + pglColor4ubv( colorArray[0] ); + } + else if( r_backacc.numColors > 1 ) + { + pglEnableClientState( GL_COLOR_ARRAY ); + R_UpdateVertexBuffer( tr.colorsBuffer, colorArray, r_backacc.numVerts * sizeof( rgba_t )); + pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tr.colorsBuffer->pointer ); + } + + if( r_drawelements->integer || glState.in2DMode || RI.refdef.rdflags & RDF_NOWORLDMODEL ) + { + if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) + pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); + else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); + } + + if( r_backacc.numColors > 1 ) + pglDisableClientState( GL_COLOR_ARRAY ); + + r_backacc.c_totalTris += r_backacc.numElems / 3; + r_backacc.c_totalFlushes++; +} + +/* +============== +GL_DisableAllTexGens +============== +*/ +static _inline void GL_DisableAllTexGens( void ) +{ + GL_EnableTexGen( GL_S, 0 ); + GL_EnableTexGen( GL_T, 0 ); + GL_EnableTexGen( GL_R, 0 ); + GL_EnableTexGen( GL_Q, 0 ); +} + +/* +============== +R_CleanUpTextureUnits +============== +*/ +static void R_CleanUpTextureUnits( int last ) +{ + int i; + + for( i = glState.activeTMU; i > last - 1; i-- ) + { + GL_DisableAllTexGens(); + GL_SetTexCoordArrayMode( 0 ); + + pglDisable( GL_TEXTURE_2D ); + GL_SelectTexture( i - 1 ); + } +} + +/* +================ +R_DeformVertices +================ +*/ +void R_DeformVertices( void ) +{ + uint i, j, k; + double args[4], temp; + float deflect, *quad[4]; + const float *table; + const deform_t *deformv; + vec3_t tv, rot_centre; + + deformv = &r_currentShader->deforms[0]; + for( i = 0; i < r_currentShader->numDeforms; i++, deformv++ ) + { + switch( deformv->type ) + { + case DEFORM_NONE: + break; + + case DEFORM_WAVE: + table = R_TableForFunc( deformv->func.type ); + + // Deflect vertex along its normal by wave amount + if( deformv->func.args[3] == 0 ) + { + temp = deformv->func.args[2]; + deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0]; + + for( j = 0; j < r_backacc.numVerts; j++ ) + VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); + } + else + { + args[0] = deformv->func.args[0]; + args[1] = deformv->func.args[1]; + args[2] = deformv->func.args[2] + deformv->func.args[3] * r_currentShaderTime; + args[3] = deformv->args[0]; + + for( j = 0; j < r_backacc.numVerts; j++ ) + { + temp = args[2] + args[3] * ( inVertsArray[j][0] + inVertsArray[j][1] + inVertsArray[j][2] ); + deflect = FTABLE_EVALUATE( table, temp ) * args[1] + args[0]; + VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); + } + } + break; + + case DEFORM_NORMAL: + // without this * 0.1f deformation looks wrong, although q3a doesn't have it + args[0] = deformv->func.args[3] * r_currentShaderTime * 0.1f; + args[1] = deformv->func.args[1]; + + for( j = 0; j < r_backacc.numVerts; j++ ) + { + VectorScale( inVertsArray[j], 0.98f, tv ); + inNormalsArray[j][0] += args[1] *R_BackendGetNoiseValue( tv[0], tv[1], tv[2], args[0] ); + inNormalsArray[j][1] += args[1] *R_BackendGetNoiseValue( tv[0] + 100, tv[1], tv[2], args[0] ); + inNormalsArray[j][2] += args[1] *R_BackendGetNoiseValue( tv[0] + 200, tv[1], tv[2], args[0] ); + VectorNormalizeFast( inNormalsArray[j] ); + } + break; + + case DEFORM_MOVE: + table = R_TableForFunc( deformv->func.type ); + temp = deformv->func.args[2] + r_currentShaderTime * deformv->func.args[3]; + deflect = FTABLE_EVALUATE( table, temp ) * deformv->func.args[1] + deformv->func.args[0]; + + for( j = 0; j < r_backacc.numVerts; j++ ) + VectorMA( inVertsArray[j], deflect, deformv->args, inVertsArray[j] ); + break; + + case DEFORM_BULGE: + args[0] = deformv->args[0]; + args[1] = deformv->args[1]; + args[2] = r_currentShaderTime * deformv->args[2]; + + for( j = 0; j < r_backacc.numVerts; j++ ) + { + temp = ( coordsArray[j][0] * args[0] + args[2] ) / M_PI2; + deflect = R_FastSin( temp ) * args[1]; + VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); + } + break; + + case DEFORM_AUTOSPRITE: + { + vec4_t *v; + vec2_t *st; + elem_t *elem; + float radius; + vec3_t point, v_centre, v_right, v_up; + + if( r_backacc.numVerts % 4 || r_backacc.numElems % 6 ) + break; + + if( RI.currententity && (RI.currentmodel != r_worldmodel) ) + { + Matrix_TransformVector( RI.currententity->axis, RI.vright, v_right ); + Matrix_TransformVector( RI.currententity->axis, RI.vup, v_up ); + } + else + { + VectorCopy( RI.vright, v_right ); + VectorCopy( RI.vup, v_up ); + } + + radius = RI.currententity->scale; + if( radius && radius != 1.0f ) + { + radius = 1.0f / radius; + VectorScale( v_right, radius, v_right ); + VectorScale( v_up, radius, v_up ); + } + + for( k = 0, v = inVertsArray, st = coordsArray, elem = elemsArray; k < r_backacc.numVerts; k += 4, v += 4, st += 4, elem += 6 ) + { + for( j = 0; j < 3; j++ ) + v_centre[j] = (v[0][j] + v[1][j] + v[2][j] + v[3][j]) * 0.25; + + VectorSubtract( v[0], v_centre, point ); + radius = VectorLength( point ) * 0.707106f; // 1.0f / sqrt(2) + + // very similar to R_PushSprite + VectorMA( v_centre, -radius, v_up, point ); + VectorMA( point, -radius, v_right, v[0] ); + VectorMA( point, radius, v_right, v[3] ); + + VectorMA( v_centre, radius, v_up, point ); + VectorMA( point, -radius, v_right, v[1] ); + VectorMA( point, radius, v_right, v[2] ); + + // reset texcoords + Vector2Set( st[0], 0, 1 ); + Vector2Set( st[1], 0, 0 ); + Vector2Set( st[2], 1, 0 ); + Vector2Set( st[3], 1, 1 ); + + // trifan elems + elem[0] = k; + elem[1] = k + 2 - 1; + elem[2] = k + 2; + + elem[3] = k; + elem[4] = k + 3 - 1; + elem[5] = k + 3; + } + } + break; + + case DEFORM_AUTOSPRITE2: + if( r_backacc.numElems % 6 ) + break; + + for( k = 0; k < r_backacc.numElems; k += 6 ) + { + int long_axis = 0, short_axis = 0; + vec3_t axis, tmp; + float len[3]; + vec3_t m0[3], m1[3], m2[3], result[3]; + + quad[0] = ( float * )( inVertsArray + elemsArray[k+0] ); + quad[1] = ( float * )( inVertsArray + elemsArray[k+1] ); + quad[2] = ( float * )( inVertsArray + elemsArray[k+2] ); + + for( j = 2; j >= 0; j-- ) + { + quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] ); + + if( !VectorCompare( quad[3], quad[0] ) && + !VectorCompare( quad[3], quad[1] ) && + !VectorCompare( quad[3], quad[2] ) ) + { + break; + } + } + + // build a matrix were the longest axis of the billboard is the Y-Axis + VectorSubtract( quad[1], quad[0], m0[0] ); + VectorSubtract( quad[2], quad[0], m0[1] ); + VectorSubtract( quad[2], quad[1], m0[2] ); + len[0] = DotProduct( m0[0], m0[0] ); + len[1] = DotProduct( m0[1], m0[1] ); + len[2] = DotProduct( m0[2], m0[2] ); + + if( ( len[2] > len[1] ) && ( len[2] > len[0] ) ) + { + if( len[1] > len[0] ) + { + long_axis = 1; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 1; + } + } + else if( ( len[1] > len[2] ) && ( len[1] > len[0] ) ) + { + if( len[2] > len[0] ) + { + long_axis = 2; + short_axis = 0; + } + else + { + long_axis = 0; + short_axis = 2; + } + } + else if( ( len[0] > len[1] ) && ( len[0] > len[2] ) ) + { + if( len[2] > len[1] ) + { + long_axis = 2; + short_axis = 1; + } + else + { + long_axis = 1; + short_axis = 2; + } + } + + if( !len[long_axis] ) + break; + len[long_axis] = Q_RSqrt( len[long_axis] ); + VectorScale( m0[long_axis], len[long_axis], axis ); + + if( DotProduct( m0[long_axis], m0[short_axis] ) ) + { + VectorCopy( axis, m0[1] ); + if( axis[0] || axis[1] ) + VectorVectors( m0[1], m0[0], m0[2] ); + else + VectorVectors( m0[1], m0[2], m0[0] ); + } + else + { + if( !len[short_axis] ) + break; + len[short_axis] = Q_RSqrt( len[short_axis] ); + VectorScale( m0[short_axis], len[short_axis], m0[0] ); + VectorCopy( axis, m0[1] ); + CrossProduct( m0[0], m0[1], m0[2] ); + } + + for( j = 0; j < 3; j++ ) + rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25; + + if( RI.currententity && ( RI.currentmodel != r_worldmodel ) ) + { + VectorAdd( RI.currententity->origin, rot_centre, tv ); + VectorSubtract( RI.viewOrigin, tv, tmp ); + Matrix_TransformVector( RI.currententity->axis, tmp, tv ); + } + else + { + VectorCopy( rot_centre, tv ); + VectorSubtract( RI.viewOrigin, tv, tv ); + } + + // filter any longest-axis-parts off the camera-direction + deflect = -DotProduct( tv, axis ); + + VectorMA( tv, deflect, axis, m1[2] ); + VectorNormalizeFast( m1[2] ); + VectorCopy( axis, m1[1] ); + CrossProduct( m1[1], m1[2], m1[0] ); + + Matrix_Transpose( m1, m2 ); + Matrix_Multiply( m2, m0, result ); + + for( j = 0; j < 4; j++ ) + { + VectorSubtract( quad[j], rot_centre, tv ); + Matrix_TransformVector( result, tv, quad[j] ); + VectorAdd( rot_centre, quad[j], quad[j] ); + } + } + break; + + case DEFORM_PROJECTION_SHADOW: + R_DeformVPlanarShadow( r_backacc.numVerts, inVertsArray[0] ); + break; + + case DEFORM_AUTOPARTICLE: + { + float scale; + vec3_t m0[3], m1[3], m2[3], result[3]; + + if( r_backacc.numElems % 6 ) + break; + + if( RI.currententity && ( RI.currentmodel != r_worldmodel ) ) + Matrix4_Matrix( RI.modelviewMatrix, m1 ); + else + Matrix4_Matrix( RI.worldviewMatrix, m1 ); + + Matrix_Transpose( m1, m2 ); + + for( k = 0; k < r_backacc.numElems; k += 6 ) + { + quad[0] = ( float * )( inVertsArray + elemsArray[k+0] ); + quad[1] = ( float * )( inVertsArray + elemsArray[k+1] ); + quad[2] = ( float * )( inVertsArray + elemsArray[k+2] ); + + for( j = 2; j >= 0; j-- ) + { + quad[3] = ( float * )( inVertsArray + elemsArray[k+3+j] ); + + if( !VectorCompare( quad[3], quad[0] ) && + !VectorCompare( quad[3], quad[1] ) && + !VectorCompare( quad[3], quad[2] ) ) + { + break; + } + } + + Matrix_FromPoints( quad[0], quad[1], quad[2], m0 ); + Matrix_Multiply( m2, m0, result ); + + // hack a scale up to keep particles from disappearing + scale = ( quad[0][0] - RI.viewOrigin[0] ) * RI.vpn[0] + ( quad[0][1] - RI.viewOrigin[1] ) * RI.vpn[1] + ( quad[0][2] - RI.viewOrigin[2] ) * RI.vpn[2]; + if( scale < 20 ) + scale = 1.5; + else + scale = 1.5 + scale * 0.006f; + + for( j = 0; j < 3; j++ ) + rot_centre[j] = ( quad[0][j] + quad[1][j] + quad[2][j] + quad[3][j] ) * 0.25; + + for( j = 0; j < 4; j++ ) + { + VectorSubtract( quad[j], rot_centre, tv ); + Matrix_TransformVector( result, tv, quad[j] ); + VectorMA( rot_centre, scale, quad[j], quad[j] ); + } + } + } + break; + case DEFORM_OUTLINE: + // Deflect vertex along its normal by outline amount + deflect = RI.currententity->outlineHeight * r_outlines_scale->value; + for( j = 0; j < r_backacc.numVerts; j++ ) + VectorMA( inVertsArray[j], deflect, inNormalsArray[j], inVertsArray[j] ); + break; + default: + break; + } + } +} + +/* +============== +R_VertexTCBase +============== +*/ +static bool R_VertexTCBase( const ref_stage_t *pass, int unit, mat4x4_t matrix ) +{ + unsigned int i; + float *outCoords; + bool identityMatrix = false; + + Matrix4_Identity( matrix ); + + switch( pass->tcgen ) + { + case TCGEN_BASE: + GL_DisableAllTexGens(); + + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], coordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, coordsArray ); + return true; + case TCGEN_LIGHTMAP: + GL_DisableAllTexGens(); + + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], lightmapCoordsArray[r_lightmapStyleNum[unit]], r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, lightmapCoordsArray[r_lightmapStyleNum[unit]] ); + return true; + case TCGEN_ENVIRONMENT: + { + float depth, *n; + vec3_t projection, transform; + + if( glState.in2DMode ) + return true; + + if( !( RI.params & RP_SHADOWMAPVIEW ) ) + { + VectorSubtract( RI.viewOrigin, RI.currententity->origin, projection ); + Matrix_TransformVector( RI.currententity->axis, projection, transform ); + + outCoords = tUnitCoordsArray[unit][0]; + for( i = 0, n = normalsArray[0]; i < r_backacc.numVerts; i++, outCoords += 2, n += 4 ) + { + VectorSubtract( transform, vertsArray[i], projection ); + VectorNormalizeFast( projection ); + + depth = DotProduct( n, projection ); depth += depth; + outCoords[0] = 0.5 + ( n[1] * depth - projection[1] ) * 0.5; + outCoords[1] = 0.5 - ( n[2] * depth - projection[2] ) * 0.5; + } + } + + GL_DisableAllTexGens(); + + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] ); + return true; + } + + case TCGEN_VECTOR: + { + GLfloat genVector[2][4]; + + for( i = 0; i < 3; i++ ) + { + genVector[0][i] = pass->tcgenVec[i]; + genVector[1][i] = pass->tcgenVec[i+4]; + } + genVector[0][3] = genVector[1][3] = 0; + + matrix[12] = pass->tcgenVec[3]; + matrix[13] = pass->tcgenVec[7]; + + GL_SetTexCoordArrayMode( 0 ); + GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR ); + GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR ); + GL_EnableTexGen( GL_R, 0 ); + GL_EnableTexGen( GL_Q, 0 ); + pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] ); + pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] ); + return false; + } + case TCGEN_PROJECTION: + { + mat4x4_t m1, m2; + GLfloat genVector[4][4]; + + GL_SetTexCoordArrayMode( 0 ); + + Matrix4_Copy( RI.worldviewProjectionMatrix, matrix ); + + Matrix4_Identity( m1 ); + Matrix4_Scale( m1, 0.5, 0.5, 0.5 ); + Matrix4_Multiply( m1, matrix, m2 ); + + Matrix4_Identity( m1 ); + Matrix4_Translate( m1, 0.5, 0.5, 0.5 ); + Matrix4_Multiply( m1, m2, matrix ); + + for( i = 0; i < 4; i++ ) + { + genVector[0][i] = i == 0 ? 1 : 0; + genVector[1][i] = i == 1 ? 1 : 0; + genVector[2][i] = i == 2 ? 1 : 0; + genVector[3][i] = i == 3 ? 1 : 0; + } + + GL_EnableTexGen( GL_S, GL_OBJECT_LINEAR ); + GL_EnableTexGen( GL_T, GL_OBJECT_LINEAR ); + GL_EnableTexGen( GL_R, GL_OBJECT_LINEAR ); + GL_EnableTexGen( GL_Q, GL_OBJECT_LINEAR ); + + pglTexGenfv( GL_S, GL_OBJECT_PLANE, genVector[0] ); + pglTexGenfv( GL_T, GL_OBJECT_PLANE, genVector[1] ); + pglTexGenfv( GL_R, GL_OBJECT_PLANE, genVector[2] ); + pglTexGenfv( GL_Q, GL_OBJECT_PLANE, genVector[3] ); + return false; + } + + case TCGEN_REFLECTION_CELLSHADE: + if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) ) + { + vec3_t dir; + mat4x4_t m; + + R_LightForOrigin( RI.currententity->lightingOrigin, dir, NULL, NULL, RI.currentmodel->radius * RI.currententity->scale ); + + Matrix4_Identity( m ); + + // rotate direction + Matrix_TransformVector( RI.currententity->axis, dir, &m[0] ); + VectorNormalizeLength( &m[0] ); + + VectorVectors( &m[0], &m[4], &m[8] ); + Matrix4_Transpose( m, matrix ); + } + case TCGEN_REFLECTION: + GL_EnableTexGen( GL_S, GL_REFLECTION_MAP_ARB ); + GL_EnableTexGen( GL_T, GL_REFLECTION_MAP_ARB ); + GL_EnableTexGen( GL_R, GL_REFLECTION_MAP_ARB ); + GL_EnableTexGen( GL_Q, 0 ); + return true; + + case TCGEN_FOG: + { + int fogPtype; + cplane_t *fogPlane; + ref_shader_t *fogShader; + vec3_t viewtofog; + float fogNormal[3], vpnNormal[3]; + float dist, vdist, fogDist, vpnDist; + + fogPlane = r_texFog->visibleplane; + fogShader = r_texFog->shader; + + matrix[0] = matrix[5] = 1.0/(fogShader->fog_dist - fogShader->fog_clearDist); + matrix[13] = 1.5f/(float)FOG_TEXTURE_HEIGHT; + + // distance to fog + dist = RI.fog_dist_to_eye[r_texFog-r_worldbrushmodel->fogs]; + + if( r_currentShader->flags & SHADER_SKYPARMS ) + { + if( dist > 0 ) + VectorMA( RI.viewOrigin, -dist, fogPlane->normal, viewtofog ); + else + VectorCopy( RI.viewOrigin, viewtofog ); + } + else + { + VectorCopy( RI.currententity->origin, viewtofog ); + } + + // some math tricks to take entity's rotation matrix into account + // for fog texture coordinates calculations: + // M is rotation matrix, v is vertex, t is transform vector + // n is plane's normal, d is plane's dist, r is view origin + // (M*v + t)*n - d = (M*n)*v - ((d - t*n)) + // (M*v + t - r)*n = (M*n)*v - ((r - t)*n) + fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale; + fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale; + fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale; + fogPtype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) ); + fogDist = ( fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ) ); + + vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * RI.currententity->scale; + vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * RI.currententity->scale; + vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * RI.currententity->scale; + vpnDist = ( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) + fogShader->fog_clearDist; + + outCoords = tUnitCoordsArray[unit][0]; + if( dist < 0 ) + { // camera is inside the fog brush + for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 ) + { + outCoords[0] = DotProduct( vertsArray[i], vpnNormal ) - vpnDist; + if( fogPtype < 3 ) + outCoords[1] = -( vertsArray[i][fogPtype] - fogDist ); + else + outCoords[1] = -( DotProduct( vertsArray[i], fogNormal ) - fogDist ); + } + } + else + { + for( i = 0; i < r_backacc.numVerts; i++, outCoords += 2 ) + { + if( fogPtype < 3 ) + vdist = vertsArray[i][fogPtype] - fogDist; + else + vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist; + outCoords[0] = ( ( vdist < 0 ) ? ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ) : 0.0f ); + outCoords[1] = -vdist; + } + } + + GL_DisableAllTexGens(); + + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], tUnitCoordsArray, r_backacc.numVerts * sizeof( vec2_t )); + pglTexCoordPointer( 2, GL_FLOAT, 0, tUnitCoordsArray[unit] ); + return false; + } + + case TCGEN_SVECTORS: + GL_DisableAllTexGens(); + R_UpdateVertexBuffer( tr.tcoordBuffer[unit], sVectorsArray, r_backacc.numVerts * sizeof( vec4_t )); + pglTexCoordPointer( 4, GL_FLOAT, 0, sVectorsArray ); + return true; + case TCGEN_PROJECTION_SHADOW: + GL_SetTexCoordArrayMode( 0 ); + GL_DisableAllTexGens(); + Matrix4_Multiply( r_currentCastGroup->worldviewProjectionMatrix, RI.objectMatrix, matrix ); + break; + default: break; + } + return identityMatrix; +} + +/* +================ +R_ApplyTCMods +================ +*/ +static void R_ApplyTCMods( const ref_stage_t *pass, mat4x4_t result ) +{ + int i; + const float *table; + double t1, t2, sint, cost; + mat4x4_t m1, m2; + const tcMod_t *tcmod; + + for( i = 0, tcmod = pass->tcMods; i < pass->numtcMods; i++, tcmod++ ) + { + switch( tcmod->type ) + { + case TCMOD_ROTATE: + cost = tcmod->args[0] * r_currentShaderTime; + sint = R_FastSin( cost ); + cost = R_FastSin( cost + 0.25 ); + m2[0] = cost, m2[1] = sint, m2[12] = 0.5f * ( sint - cost + 1 ); + m2[4] = -sint, m2[5] = cost, m2[13] = -0.5f * ( sint + cost - 1 ); + Matrix4_Copy2D( result, m1 ); + Matrix4_Multiply2D( m2, m1, result ); + break; + case TCMOD_SCALE: + Matrix4_Scale2D( result, tcmod->args[0], tcmod->args[1] ); + break; + case TCMOD_TURB: + t1 = ( 1.0 / 4.0 ); + t2 = tcmod->args[2] + r_currentShaderTime * tcmod->args[3]; + Matrix4_Scale2D( result, 1 + ( tcmod->args[1] * R_FastSin( t2 ) + tcmod->args[0] ) * t1, 1 + ( tcmod->args[1] * R_FastSin( t2 + 0.25 ) + tcmod->args[0] ) * t1 ); + break; + case TCMOD_STRETCH: + table = R_TableForFunc( tcmod->args[0] ); + t2 = tcmod->args[3] + r_currentShaderTime * tcmod->args[4]; + t1 = FTABLE_EVALUATE( table, t2 ) * tcmod->args[2] + tcmod->args[1]; + t1 = t1 ? 1.0f / t1 : 1.0f; + t2 = 0.5f - 0.5f * t1; + Matrix4_Stretch2D( result, t1, t2 ); + break; + case TCMOD_SCROLL: + t1 = tcmod->args[0] * r_currentShaderTime; + t2 = tcmod->args[1] * r_currentShaderTime; + if( pass->program_type != PROGRAM_TYPE_DISTORTION ) + { // HACK HACK HACK + t1 = t1 - floor( t1 ); + t2 = t2 - floor( t2 ); + } + Matrix4_Translate2D( result, t1, t2 ); + break; + case TCMOD_TRANSFORM: + m2[0] = tcmod->args[0], m2[1] = tcmod->args[2], m2[12] = tcmod->args[4], + m2[5] = tcmod->args[1], m2[4] = tcmod->args[3], m2[13] = tcmod->args[5]; + Matrix4_Copy2D( result, m1 ); + Matrix4_Multiply2D( m2, m1, result ); + break; + default: + break; + } + } +} + +/* +============== +R_ShaderpassTex +============== +*/ +static _inline texture_t *R_ShaderpassTex( const ref_stage_t *pass, int unit ) +{ + if( pass->flags & SHADERSTAGE_ANIMFREQUENCY && pass->animFrequency && pass->num_textures ) + return pass->textures[(int)( pass->animFrequency * r_currentShaderTime ) % pass->num_textures]; + if( pass->flags & SHADERSTAGE_LIGHTMAP ) + return tr.lightmapTextures[r_superLightStyle->lightmapNum[r_lightmapStyleNum[unit]]]; + if( pass->flags & SHADERSTAGE_PORTALMAP ) + return tr.portaltexture1; + return ( pass->textures[0] ? pass->textures[0] : tr.defaultTexture ); +} + +/* +================ +R_BindShaderpass +================ +*/ +static void R_BindShaderpass( const ref_stage_t *pass, texture_t *tex, int unit ) +{ + mat4x4_t m1, m2, result; + bool identityMatrix; + + if( !tex ) + tex = R_ShaderpassTex( pass, unit ); + + GL_Bind( unit, tex ); + if( unit && !pass->program ) pglEnable( GL_TEXTURE_2D ); + GL_SetTexCoordArrayMode( ( tex->flags & TF_CUBEMAP ? GL_TEXTURE_CUBE_MAP_ARB : GL_TEXTURE_COORD_ARRAY )); + + identityMatrix = R_VertexTCBase( pass, unit, result ); + + if( pass->numtcMods ) + { + identityMatrix = false; + R_ApplyTCMods( pass, result ); + } + + if( pass->tcgen == TCGEN_REFLECTION || pass->tcgen == TCGEN_REFLECTION_CELLSHADE ) + { + Matrix4_Transpose( RI.modelviewMatrix, m1 ); + Matrix4_Copy( result, m2 ); + Matrix4_Multiply( m2, m1, result ); + GL_LoadTexMatrix( result ); + return; + } + + if( identityMatrix ) + GL_LoadIdentityTexMatrix(); + else + GL_LoadTexMatrix( result ); +} + +/* +================ +R_ModifyColor +================ +*/ +void R_ModifyColor( const ref_stage_t *pass ) +{ + uint i; + int c, bits; + double temp; + float *table, a; + vec3_t t, v, style; + byte *bArray, *inArray, rgba[4] = { 255, 255, 255, 255 }; + bool noArray, identityAlpha, entityAlpha; + const waveFunc_t *rgbgenfunc, *alphagenfunc; + + noArray = ( pass->flags & SHADERSTAGE_NOCOLORARRAY ) && !r_colorFog; + r_backacc.numColors = noArray ? 1 : r_backacc.numVerts; + bits = ( r_overbrightbits->integer > 0 ) && !( r_ignorehwgamma->integer ) ? r_overbrightbits->integer : 0; + + bArray = colorArray[0]; + inArray = inColorsArray[0][0]; + + if( pass->rgbGen.type == RGBGEN_IDENTITY_LIGHTING ) + { + entityAlpha = identityAlpha = false; + memset( bArray, r_identityLighting, sizeof( rgba_t ) * r_backacc.numColors ); + } + else if( pass->rgbGen.type == RGBGEN_EXACT_VERTEX ) + { + entityAlpha = identityAlpha = false; + memcpy( bArray, inArray, sizeof( rgba_t ) * r_backacc.numColors ); + } + else + { + entityAlpha = false; + identityAlpha = true; + memset( bArray, 255, sizeof( rgba_t ) * r_backacc.numColors ); + + switch( pass->rgbGen.type ) + { + case RGBGEN_IDENTITY: + break; + case RGBGEN_CONST: + rgba[0] = R_FloatToByte( pass->rgbGen.args[0] ); + rgba[1] = R_FloatToByte( pass->rgbGen.args[1] ); + rgba[2] = R_FloatToByte( pass->rgbGen.args[2] ); + + for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_WAVE: + rgbgenfunc = pass->rgbGen.func; + if( rgbgenfunc->type == WAVEFORM_NOISE ) + { + temp = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + rgbgenfunc->args[2] ) * rgbgenfunc->args[3] ); + } + else + { + table = R_TableForFunc( rgbgenfunc->type ); + temp = r_currentShaderTime * rgbgenfunc->args[3] + rgbgenfunc->args[2]; + temp = FTABLE_EVALUATE( table, temp ) * rgbgenfunc->args[1] + rgbgenfunc->args[0]; + } + + temp = temp * rgbgenfunc->args[1] + rgbgenfunc->args[0]; + a = pass->rgbGen.args[0] * temp; rgba[0] = a <= 0 ? 0 : R_FloatToByte( a ); + a = pass->rgbGen.args[1] * temp; rgba[1] = a <= 0 ? 0 : R_FloatToByte( a ); + a = pass->rgbGen.args[2] * temp; rgba[2] = a <= 0 ? 0 : R_FloatToByte( a ); + + for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_ENTITY: + entityAlpha = true; + identityAlpha = ( RI.currententity->color[3] == 255 ); + + for( i = 0, c = *(int *)RI.currententity->color; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_OUTLINE: + identityAlpha = ( RI.currententity->outlineColor[3] == 255 ); + + for( i = 0, c = *(int *)RI.currententity->outlineColor; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_ONE_MINUS_ENTITY: + rgba[0] = 255 - RI.currententity->color[0]; + rgba[1] = 255 - RI.currententity->color[1]; + rgba[2] = 255 - RI.currententity->color[2]; + + for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_VERTEX: + VectorSet( style, -1, -1, -1 ); + + if( !r_superLightStyle || r_superLightStyle->vertexStyles[1] == 255 ) + { + VectorSet( style, 1, 1, 1 ); + if( r_superLightStyle && r_superLightStyle->vertexStyles[0] != 255 ) + VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[0]].rgb, style ); + } + + if( style[0] == style[1] && style[1] == style[2] && style[2] == 1 ) + { + for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) + { + bArray[0] = inArray[0] >> bits; + bArray[1] = inArray[1] >> bits; + bArray[2] = inArray[2] >> bits; + } + } + else + { + int j; + float *tc; + vec3_t temp[MAX_ARRAY_VERTS]; + + memset( temp, 0, sizeof( vec3_t ) * r_backacc.numColors ); + + for( j = 0; j < LM_STYLES && r_superLightStyle->vertexStyles[j] != 255; j++ ) + { + VectorCopy( r_lightStyles[r_superLightStyle->vertexStyles[j]].rgb, style ); + if( VectorCompare( style, vec3_origin ) ) + continue; + + inArray = inColorsArray[j][0]; + for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, inArray += 4 ) + { + tc[0] += ( inArray[0] >> bits ) * style[0]; + tc[1] += ( inArray[1] >> bits ) * style[1]; + tc[2] += ( inArray[2] >> bits ) * style[2]; + } + } + + for( i = 0, tc = temp[0]; i < r_backacc.numColors; i++, tc += 3, bArray += 4 ) + { + bArray[0] = bound( 0, tc[0], 255 ); + bArray[1] = bound( 0, tc[1], 255 ); + bArray[2] = bound( 0, tc[2], 255 ); + } + } + break; + case RGBGEN_ONE_MINUS_VERTEX: + for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) + { + bArray[0] = 255 - ( inArray[0] >> bits ); + bArray[1] = 255 - ( inArray[1] >> bits ); + bArray[2] = 255 - ( inArray[2] >> bits ); + } + break; + case RGBGEN_LIGHTING_DIFFUSE: + if( RI.currententity ) + R_LightForEntity( RI.currententity, bArray ); + break; + case RGBGEN_LIGHTING_DIFFUSE_ONLY: + if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) ) + { + vec4_t diffuse; + + if( RI.currententity->flags & RF_FULLBRIGHT ) + VectorSet( diffuse, 1, 1, 1 ); + else + R_LightForOrigin( RI.currententity->lightingOrigin, t, NULL, diffuse, RI.currentmodel->radius * RI.currententity->scale ); + + rgba[0] = R_FloatToByte( diffuse[0] ); + rgba[1] = R_FloatToByte( diffuse[1] ); + rgba[2] = R_FloatToByte( diffuse[2] ); + + for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + } + break; + case RGBGEN_LIGHTING_AMBIENT_ONLY: + if( RI.currententity && !( RI.params & RP_SHADOWMAPVIEW ) ) + { + vec4_t ambient; + + if( RI.currententity->flags & RF_FULLBRIGHT ) + VectorSet( ambient, 1, 1, 1 ); + else + R_LightForOrigin( RI.currententity->lightingOrigin, t, ambient, NULL, RI.currentmodel->radius * RI.currententity->scale ); + + rgba[0] = R_FloatToByte( ambient[0] ); + rgba[1] = R_FloatToByte( ambient[1] ); + rgba[2] = R_FloatToByte( ambient[2] ); + + for( i = 0, c = *(int *)rgba; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + } + break; + case RGBGEN_FOG: + for( i = 0, c = *(int *)r_texFog->shader->fog_color; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_CUSTOM: + c = (int)pass->rgbGen.args[0]; + for( i = 0, c = R_GetCustomColor( c ); i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + case RGBGEN_ENVIRONMENT: + for( i = 0, c = *(int *)mapConfig.environmentColor; i < r_backacc.numColors; i++, bArray += 4 ) + *(int *)bArray = c; + break; + default: + break; + } + } + + bArray = colorArray[0]; + inArray = inColorsArray[0][0]; + + switch( pass->alphaGen.type ) + { + case ALPHAGEN_IDENTITY: + if( identityAlpha ) + break; + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = 255; + break; + case ALPHAGEN_CONST: + c = R_FloatToByte( pass->alphaGen.args[0] ); + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = c; + break; + case ALPHAGEN_WAVE: + alphagenfunc = pass->alphaGen.func; + if( alphagenfunc->type == WAVEFORM_NOISE ) + { + a = R_BackendGetNoiseValue( 0, 0, 0, ( r_currentShaderTime + alphagenfunc->args[2] ) * alphagenfunc->args[3] ); + } + else + { + table = R_TableForFunc( alphagenfunc->type ); + a = alphagenfunc->args[2] + r_currentShaderTime * alphagenfunc->args[3]; + a = FTABLE_EVALUATE( table, a ); + } + + a = a * alphagenfunc->args[1] + alphagenfunc->args[0]; + c = a <= 0 ? 0 : R_FloatToByte( a ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = c; + break; + case ALPHAGEN_PORTAL: + VectorAdd( vertsArray[0], RI.currententity->origin, v ); + VectorSubtract( RI.viewOrigin, v, t ); + a = VectorLength( t ) * pass->alphaGen.args[0]; + a = bound( 0.0f, a, 1.0f ); + c = R_FloatToByte( a ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = c; + break; + case ALPHAGEN_VERTEX: + for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) + bArray[3] = inArray[3]; + break; + case ALPHAGEN_ONE_MINUS_VERTEX: + for( i = 0; i < r_backacc.numColors; i++, bArray += 4, inArray += 4 ) + bArray[3] = 255 - inArray[3]; + break; + case ALPHAGEN_ENTITY: + if( entityAlpha ) + break; + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = RI.currententity->color[3]; + break; + case ALPHAGEN_OUTLINE: + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + bArray[3] = RI.currententity->outlineColor[3]; + break; + case ALPHAGEN_SPECULAR: + VectorSubtract( RI.viewOrigin, RI.currententity->origin, t ); + if( !Matrix_Compare( RI.currententity->axis, axis_identity ) ) + Matrix_TransformVector( RI.currententity->axis, t, v ); + else + VectorCopy( t, v ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + { + VectorSubtract( v, vertsArray[i], t ); + c = VectorLength( t ); + a = DotProduct( t, normalsArray[i] ) / max( 0.1, c ); + a = pow( a, pass->alphaGen.args[0] ); + bArray[3] = a <= 0 ? 0 : R_FloatToByte( a ); + } + break; + case ALPHAGEN_DOT: + if( !Matrix_Compare( RI.currententity->axis, axis_identity ) ) + Matrix_TransformVector( RI.currententity->axis, RI.vpn, v ); + else + VectorCopy( RI.vpn, v ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + { + a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a; + bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) ); + } + break; + case ALPHAGEN_ONE_MINUS_DOT: + if( !Matrix_Compare( RI.currententity->axis, axis_identity ) ) + Matrix_TransformVector( RI.currententity->axis, RI.vpn, v ); + else + VectorCopy( RI.vpn, v ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + { + a = DotProduct( v, inNormalsArray[i] ); if( a < 0 ) a = -a;a = 1.0f - a; + bArray[3] = R_FloatToByte( bound( pass->alphaGen.args[0], a, pass->alphaGen.args[1] ) ); + } + default: + break; + } + + if( r_colorFog ) + { + float dist, vdist; + cplane_t *fogPlane; + vec3_t viewtofog; + float fogNormal[3], vpnNormal[3]; + float fogDist, vpnDist, fogShaderDistScale; + int fogptype; + bool alphaFog; + int blendsrc, blenddst; + + blendsrc = pass->glState & GLSTATE_SRCBLEND_MASK; + blenddst = pass->glState & GLSTATE_DSTBLEND_MASK; + if(( blendsrc != GLSTATE_SRCBLEND_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_SRC_ALPHA ) && ( blendsrc != GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA && blenddst != GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA )) + alphaFog = false; + else alphaFog = true; + + fogPlane = r_colorFog->visibleplane; + fogShaderDistScale = 1.0 / (r_colorFog->shader->fog_dist - r_colorFog->shader->fog_clearDist); + dist = RI.fog_dist_to_eye[r_colorFog-r_worldbrushmodel->fogs]; + + if( r_currentShader->flags & SHADER_SKYPARMS ) + { + if( dist > 0 ) + VectorScale( fogPlane->normal, -dist, viewtofog ); + else + VectorClear( viewtofog ); + } + else + { + VectorCopy( RI.currententity->origin, viewtofog ); + } + + vpnNormal[0] = DotProduct( RI.currententity->axis[0], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; + vpnNormal[1] = DotProduct( RI.currententity->axis[1], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; + vpnNormal[2] = DotProduct( RI.currententity->axis[2], RI.vpn ) * fogShaderDistScale * RI.currententity->scale; + vpnDist = (( ( RI.viewOrigin[0] - viewtofog[0] ) * RI.vpn[0] + ( RI.viewOrigin[1] - viewtofog[1] ) * RI.vpn[1] + ( RI.viewOrigin[2] - viewtofog[2] ) * RI.vpn[2] ) + + r_colorFog->shader->fog_clearDist) * fogShaderDistScale; + + bArray = colorArray[0]; + if( dist < 0 ) + { // camera is inside the fog + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + { + temp = DotProduct( vertsArray[i], vpnNormal ) - vpnDist; + c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF; + + if( alphaFog ) + { + bArray[3] = ( bArray[3] * c ) >> 16; + } + else + { + bArray[0] = ( bArray[0] * c ) >> 16; + bArray[1] = ( bArray[1] * c ) >> 16; + bArray[2] = ( bArray[2] * c ) >> 16; + } + } + } + else + { + fogNormal[0] = DotProduct( RI.currententity->axis[0], fogPlane->normal ) * RI.currententity->scale; + fogNormal[1] = DotProduct( RI.currententity->axis[1], fogPlane->normal ) * RI.currententity->scale; + fogNormal[2] = DotProduct( RI.currententity->axis[2], fogPlane->normal ) * RI.currententity->scale; + fogptype = ( fogNormal[0] == 1.0 ? PLANE_X : ( fogNormal[1] == 1.0 ? PLANE_Y : ( fogNormal[2] == 1.0 ? PLANE_Z : PLANE_NONAXIAL ) ) ); + fogDist = fogPlane->dist - DotProduct( viewtofog, fogPlane->normal ); + + for( i = 0; i < r_backacc.numColors; i++, bArray += 4 ) + { + if( fogptype < 3 ) + vdist = vertsArray[i][fogptype] - fogDist; + else + vdist = DotProduct( vertsArray[i], fogNormal ) - fogDist; + + if( vdist < 0 ) + { + temp = ( DotProduct( vertsArray[i], vpnNormal ) - vpnDist ) * vdist / ( vdist - dist ); + c = ( 1.0f - bound( 0, temp, 1.0f ) ) * 0xFFFF; + + if( alphaFog ) + { + bArray[3] = ( bArray[3] * c ) >> 16; + } + else + { + bArray[0] = ( bArray[0] * c ) >> 16; + bArray[1] = ( bArray[1] * c ) >> 16; + bArray[2] = ( bArray[2] * c ) >> 16; + } + } + } + } + } +} + +/* +================ +R_ShaderpassBlendmode +================ +*/ +static int R_ShaderpassBlendmode( int passFlags ) +{ + if( passFlags & SHADERSTAGE_BLEND_REPLACE ) + return GL_REPLACE; + if( passFlags & SHADERSTAGE_BLEND_MODULATE ) + return GL_MODULATE; + if( passFlags & SHADERSTAGE_BLEND_ADD ) + return GL_ADD; + if( passFlags & SHADERSTAGE_BLEND_DECAL ) + return GL_DECAL; + return 0; +} + +/* +================ +R_SetShaderState +================ +*/ +static void R_SetShaderState( void ) +{ + int state; + + // Face culling + if( !gl_cull->integer || ( r_features & MF_NOCULL )) + GL_Cull( 0 ); + else if( r_currentShader->flags & SHADER_CULL_FRONT ) + GL_Cull( GL_FRONT ); + else if( r_currentShader->flags & SHADER_CULL_BACK ) + GL_Cull( GL_BACK ); + else GL_Cull( 0 ); + + state = 0; + if( r_currentShader->flags & SHADER_POLYGONOFFSET || RI.params & RP_SHADOWMAPVIEW ) + state |= GLSTATE_OFFSET_FILL; + if( r_currentShader->type == SHADER_FLARE ) + state |= GLSTATE_NO_DEPTH_TEST; + r_currentShaderState = state; +} + +/* +================ +R_RenderMeshGeneric +================ +*/ +void R_RenderMeshGeneric( void ) +{ + const ref_stage_t *pass = r_accumPasses[0]; + + R_BindShaderpass( pass, NULL, 0 ); + R_ModifyColor( pass ); + + if( pass->flags & SHADERSTAGE_BLEND_REPLACE ) + GL_TexEnv( GL_REPLACE ); + else + GL_TexEnv( GL_MODULATE ); + GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); + + R_FlushArrays(); +} + +/* +================ +R_RenderMeshMultitextured +================ +*/ +void R_RenderMeshMultitextured( void ) +{ + int i; + const ref_stage_t *pass = r_accumPasses[0]; + + R_BindShaderpass( pass, NULL, 0 ); + R_ModifyColor( pass ); + + GL_TexEnv( GL_MODULATE ); + GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX ); + + for( i = 1; i < r_numAccumPasses; i++ ) + { + pass = r_accumPasses[i]; + R_BindShaderpass( pass, NULL, i ); + GL_TexEnv( R_ShaderpassBlendmode( pass->flags ) ); + } + + R_FlushArrays(); +} + +/* +================ +R_RenderMeshCombined +================ +*/ +void R_RenderMeshCombined( void ) +{ + int i; + const ref_stage_t *pass = r_accumPasses[0]; + + R_BindShaderpass( pass, NULL, 0 ); + R_ModifyColor( pass ); + + GL_TexEnv( GL_MODULATE ); + GL_SetState( r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX ); + + for( i = 1; i < r_numAccumPasses; i++ ) + { + pass = r_accumPasses[i]; + R_BindShaderpass( pass, NULL, i ); + + if( pass->flags & ( SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE )) + { + GL_TexEnv( GL_MODULATE ); + } + else if( pass->flags & SHADERSTAGE_BLEND_ADD ) + { + // these modes are best set with TexEnv, Combine4 would need much more setup + GL_TexEnv( GL_ADD ); + } + else if( pass->flags & SHADERSTAGE_BLEND_DECAL ) + { + // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, they're added + // this way it can be possible to use GL_DECAL in both texture-units, while still looking good + // normal mutlitexturing would multiply the alpha-channel which looks ugly + GL_TexEnv( GL_COMBINE_ARB ); + pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB ); + pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_ADD ); + + pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE ); + pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR ); + pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE ); + pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA ); + + pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB ); + pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR ); + pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS_ARB ); + pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA ); + + pglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE ); + pglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA ); + } + else + { + Com_Assert( 1 ); + } + } + + R_FlushArrays(); +} + +/* +================ +R_RenderMeshGLSL_Material +================ +*/ +static void R_RenderMeshGLSL_Material( void ) +{ + int i, tcgen; + int state; + bool breakIntoPasses = false; + int program, object; + int programFeatures = 0; + texture_t *base, *normalmap, *glossmap, *decalmap; + mat4x4_t unused; + vec3_t lightDir = { 0.0f, 0.0f, 0.0f }; + vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f }; + float offsetmappingScale; + superLightStyle_t *lightStyle; + ref_stage_t *pass = r_accumPasses[0]; + + // handy pointers + base = pass->textures[0]; + normalmap = pass->textures[1]; + glossmap = pass->textures[2]; + decalmap = pass->textures[3]; + + Com_Assert( normalmap == NULL ); + + if( normalmap->samples == 4 ) + offsetmappingScale = r_offsetmapping_scale->value * r_currentShader->offsetmapping_scale; + else // no alpha in normalmap, don't bother with offset mapping + offsetmappingScale = 0; + + if( GL_Support( R_GLSL_BRANCHING )) + programFeatures |= PROGRAM_APPLY_BRANCHING; + if( GL_Support( R_GLSL_NO_HALF_TYPES )) + programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES; + if( RI.params & RP_CLIPPLANE ) + programFeatures |= PROGRAM_APPLY_CLIPPING; + + if( r_currentMeshBuffer->infokey > 0 ) + { + // world surface + int srcAlpha = (pass->flags & SHADERSTAGE_BLEND_DECAL); + + // CHECKTHIS: this is right ? + srcAlpha |= (pass->glState & (GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_DSTBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA)); + + if( !( r_offsetmapping->integer & 1 ) ) + offsetmappingScale = 0; + + if( r_lightmap->integer || ( r_currentDlightBits && !pass->textures[5] ) ) + { + if( !srcAlpha ) + base = tr.whiteTexture; // white + else + programFeatures |= PROGRAM_APPLY_BASETEX_ALPHA_ONLY; + } + + // we use multipass for dynamic lights, so bind the white texture + // instead of base in GLSL program and add another modulative pass (diffusemap) + if( !r_lightmap->integer && ( r_currentDlightBits && !pass->textures[5] ) ) + { + breakIntoPasses = true; + r_GLSLpasses[1] = *pass; + r_GLSLpasses[1].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_MODULATE; + r_GLSLpasses[1].glState = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0); + + // decal + if( decalmap ) + { + r_GLSLpasses[1].rgbGen.type = RGBGEN_IDENTITY; + r_GLSLpasses[1].alphaGen.type = ALPHAGEN_IDENTITY; + + r_GLSLpasses[2] = *pass; + r_GLSLpasses[2].flags = ( pass->flags & SHADERSTAGE_NOCOLORARRAY )|SHADERSTAGE_BLEND_DECAL; + r_GLSLpasses[2].glState = GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|((pass->glState & GLSTATE_ALPHAFUNC) ? GLSTATE_DEPTHFUNC_EQ : 0); + r_GLSLpasses[2].textures[0] = decalmap; + } + + if( offsetmappingScale <= 0 ) + { + r_GLSLpasses[1].program = r_GLSLpasses[2].program = NULL; + r_GLSLpasses[1].program_type = r_GLSLpasses[2].program_type = PROGRAM_TYPE_NONE; + } + else + { + r_GLSLpasses[1].textures[2] = r_GLSLpasses[2].textures[2] = NULL; // no specular + r_GLSLpasses[1].textures[3] = r_GLSLpasses[2].textures[3] = NULL; // no decal + r_GLSLpasses[1].textures[6] = r_GLSLpasses[6].textures[2] = ((texture_t *)1); // HACKHACK no ambient + } + } + } + else if( ( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY ) + { // polys + if( !( r_offsetmapping->integer & 2 ) ) + offsetmappingScale = 0; + + R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray ); + } + else + { // models + if( !( r_offsetmapping->integer & 4 ) ) + offsetmappingScale = 0; + } + + tcgen = pass->tcgen; // store the original tcgen + + pass->tcgen = TCGEN_BASE; + R_BindShaderpass( pass, base, 0 ); + if( !breakIntoPasses ) + { + // calculate the fragment color + R_ModifyColor( pass ); + } + else + { // rgbgen identity (255,255,255,255) + r_backacc.numColors = 1; + colorArray[0][0] = colorArray[0][1] = colorArray[0][2] = colorArray[0][3] = 255; + } + + // set shaderpass state (blending, depthwrite, etc) + state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; + GL_SetState( state ); + + // don't waste time on processing GLSL programs with zero colormask + if( RI.params & RP_SHADOWMAPVIEW ) + { + pass->tcgen = tcgen; // restore original tcgen + R_FlushArrays(); + return; + } + + // we only send S-vectors to GPU and recalc T-vectors as cross product + // in vertex shader + pass->tcgen = TCGEN_SVECTORS; + GL_Bind( 1, normalmap ); // normalmap + GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); + R_VertexTCBase( pass, 1, unused ); + + if( glossmap && r_lighting_glossintensity->value ) + { + programFeatures |= PROGRAM_APPLY_SPECULAR; + GL_Bind( 2, glossmap ); // gloss + GL_SetTexCoordArrayMode( 0 ); + } + + if( decalmap && !breakIntoPasses ) + { + programFeatures |= PROGRAM_APPLY_DECAL; + GL_Bind( 3, decalmap ); // decal + GL_SetTexCoordArrayMode( 0 ); + } + + if( offsetmappingScale > 0 ) + programFeatures |= r_offsetmapping_reliefmapping->integer ? PROGRAM_APPLY_RELIEFMAPPING : PROGRAM_APPLY_OFFSETMAPPING; + + if( r_currentMeshBuffer->infokey > 0 ) + { // world surface + lightStyle = r_superLightStyle; + + // bind lightmap textures and set program's features for lightstyles + if( r_superLightStyle && r_superLightStyle->lightmapNum[0] >= 0 ) + { + pass->tcgen = TCGEN_LIGHTMAP; + + for( i = 0; i < LM_STYLES && r_superLightStyle->lightmapStyles[i] != 255; i++ ) + { + programFeatures |= ( PROGRAM_APPLY_LIGHTSTYLE0 << i ); + + r_lightmapStyleNum[i+4] = i; + GL_Bind( i+4, tr.lightmapTextures[r_superLightStyle->lightmapNum[i]] ); // lightmap + GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); + R_VertexTCBase( pass, i+4, unused ); + } + + if( i == 1 ) + { + vec_t *rgb = r_lightStyles[r_superLightStyle->lightmapStyles[0]].rgb; + + // PROGRAM_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize + // the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel) + if( rgb[0] == 1 && rgb[1] == 1 && rgb[2] == 1 ) + programFeatures |= PROGRAM_APPLY_FB_LIGHTMAP; + } + } + + if( !pass->textures[6] && !VectorCompare( mapConfig.ambient, vec3_origin ) ) + { + VectorCopy( mapConfig.ambient, ambient ); + programFeatures |= PROGRAM_APPLY_AMBIENT_COMPENSATION; + } + } + else + { + vec3_t temp; + + lightStyle = NULL; + programFeatures |= PROGRAM_APPLY_DIRECTIONAL_LIGHT; + + if( ( r_currentMeshBuffer->sortkey & 3 ) == MB_POLY ) + { + VectorCopy( r_polys[-r_currentMeshBuffer->infokey-1].normal, lightDir ); + Vector4Set( ambient, 0, 0, 0, 0 ); + Vector4Set( diffuse, 1, 1, 1, 1 ); + } + else if( RI.currententity ) + { + if( RI.currententity->flags & RF_FULLBRIGHT ) + { + Vector4Set( ambient, 1, 1, 1, 1 ); + Vector4Set( diffuse, 1, 1, 1, 1 ); + } + else + { + // get weighted incoming direction of world and dynamic lights + R_LightForOrigin( RI.currententity->lightingOrigin, temp, ambient, diffuse, + RI.currententity->model ? RI.currententity->model->radius * RI.currententity->scale : 0 ); + + if( RI.currententity->flags & EF_MINLIGHT ) + { + if( ambient[0] <= 0.1f || ambient[1] <= 0.1f || ambient[2] <= 0.1f ) + VectorSet( ambient, 0.1f, 0.1f, 0.1f ); + } + + // rotate direction + Matrix_TransformVector( RI.currententity->axis, temp, lightDir ); + } + } + } + + pass->tcgen = tcgen; // restore original tcgen + + program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); + object = R_GetProgramObject( program ); + if( object ) + { + pglUseProgramObjectARB( object ); + + // update uniforms + R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle, + true, 0, 0, 0, offsetmappingScale ); + + R_FlushArrays(); + + pglUseProgramObjectARB( 0 ); + } + + if( breakIntoPasses ) + { + unsigned int oDB = r_currentDlightBits; // HACK HACK HACK + superLightStyle_t *oSL = r_superLightStyle; + + R_AccumulatePass( &r_GLSLpasses[0] ); // dynamic lighting pass + + if( offsetmappingScale ) + { + r_superLightStyle = NULL; + r_currentDlightBits = 0; + } + + R_AccumulatePass( &r_GLSLpasses[1] ); // modulate (diffusemap) + + if( decalmap ) + R_AccumulatePass( &r_GLSLpasses[2] ); // alpha-blended decal texture + + if( offsetmappingScale ) + { + r_superLightStyle = oSL; + r_currentDlightBits = oDB; + } + } +} + +/* +================ +R_RenderMeshGLSL_Distortion +================ +*/ +static void R_RenderMeshGLSL_Distortion( void ) +{ + int state, tcgen; + int program, object; + int programFeatures = 0; + mat4x4_t unused; + ref_stage_t *pass = r_accumPasses[0]; + texture_t *portaltexture1, *portaltexture2; + bool frontPlane; + + if( !( RI.params & ( RP_PORTALCAPTURED|RP_PORTALCAPTURED2 ))) + return; + + if( GL_Support( R_GLSL_BRANCHING )) + programFeatures |= PROGRAM_APPLY_BRANCHING; + if( GL_Support( R_GLSL_NO_HALF_TYPES )) + programFeatures |= PROGRAM_APPLY_NO_HALF_TYPES; + if( RI.params & RP_CLIPPLANE ) + programFeatures |= PROGRAM_APPLY_CLIPPING; + + portaltexture1 = ( RI.params & RP_PORTALCAPTURED ) ? tr.portaltexture1 : tr.blackTexture; + portaltexture2 = ( RI.params & RP_PORTALCAPTURED2 ) ? tr.portaltexture2 : tr.blackTexture; + + frontPlane = (PlaneDiff( RI.viewOrigin, &RI.portalPlane ) > 0 ? true : false); + + tcgen = pass->tcgen; // store the original tcgen + + R_BindShaderpass( pass, pass->textures[0], 0 ); // dudvmap + + // calculate the fragment color + R_ModifyColor( pass ); + + if( frontPlane ) + { + if( pass->alphaGen.type != ALPHAGEN_IDENTITY ) + programFeatures |= PROGRAM_APPLY_DISTORTION_ALPHA; + } + + // set shaderpass state (blending, depthwrite, etc) + state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; + GL_SetState( state ); + + if( pass->textures[1] /* && ( RI.params & RP_PORTALCAPTURED )*/ ) + { + // eyeDot + programFeatures |= PROGRAM_APPLY_EYEDOT; + + pass->tcgen = TCGEN_SVECTORS; + GL_Bind( 1, pass->textures[1] ); // normalmap + GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); + R_VertexTCBase( pass, 1, unused ); + } + + GL_Bind( 2, portaltexture1 ); // reflection + GL_Bind( 3, portaltexture2 ); // refraction + + pass->tcgen = tcgen; // restore original tcgen + + // update uniforms + program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); + object = R_GetProgramObject( program ); + if( object ) + { + pglUseProgramObjectARB( object ); + + R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, + frontPlane, tr.portaltexture1->width, tr.portaltexture1->height, 0, 0 ); + + R_FlushArrays(); + + pglUseProgramObjectARB( 0 ); + } +} + +/* +================ +R_RenderMeshGLSL_Shadowmap +================ +*/ +static void R_RenderMeshGLSL_Shadowmap( void ) +{ + int i; + int state; + int program, object; + int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0; + ref_stage_t *pass = r_accumPasses[0]; + + if( r_shadows_pcf->integer == 2 ) + programFeatures |= PROGRAM_APPLY_PCF2x2; + else if( r_shadows_pcf->integer == 3 ) + programFeatures |= PROGRAM_APPLY_PCF3x3; + + // update uniforms + program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); + object = R_GetProgramObject( program ); + if( !object ) + return; + + for( i = 0, r_currentCastGroup = r_shadowGroups; i < r_numShadowGroups; i++, r_currentCastGroup++ ) + { + if( !( r_currentShadowBits & r_currentCastGroup->bit ) ) + continue; + + R_BindShaderpass( pass, r_currentCastGroup->depthTexture, 0 ); + + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL ); + + // calculate the fragment color + R_ModifyColor( pass ); + + // set shaderpass state (blending, depthwrite, etc) + state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; + GL_SetState( state ); + + pglUseProgramObjectARB( object ); + + R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true, + r_currentCastGroup->depthTexture->width, r_currentCastGroup->depthTexture->height, + r_currentCastGroup->projDist, 0 ); + + R_FlushArrays(); + + pglUseProgramObjectARB( 0 ); + + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE ); + } +} + +/* +================ +R_RenderMeshGLSL_Outline +================ +*/ +static void R_RenderMeshGLSL_Outline( void ) +{ + int faceCull; + int state; + int program, object; + int programFeatures = GL_Support( R_GLSL_BRANCHING ) ? PROGRAM_APPLY_BRANCHING : 0; + ref_stage_t *pass = r_accumPasses[0]; + + if( RI.params & RP_CLIPPLANE ) + programFeatures |= PROGRAM_APPLY_CLIPPING; + + // update uniforms + program = R_RegisterGLSLProgram( pass->program, NULL, programFeatures ); + object = R_GetProgramObject( program ); + if( !object ) + return; + + faceCull = glState.faceCull; + GL_Cull( GL_BACK ); + + GL_SelectTexture( 0 ); + GL_SetTexCoordArrayMode( 0 ); + + // calculate the fragment color + R_ModifyColor( pass ); + + // set shaderpass state (blending, depthwrite, etc) + state = r_currentShaderState | ( pass->glState & r_currentShaderPassMask ) | GLSTATE_BLEND_MTEX; + GL_SetState( state ); + + pglUseProgramObjectARB( object ); + + R_UpdateProgramUniforms( program, RI.viewOrigin, vec3_origin, vec3_origin, NULL, NULL, NULL, true, + 0, 0, RI.currententity->outlineHeight * r_outlines_scale->value, 0 ); + + R_FlushArrays(); + + pglUseProgramObjectARB( 0 ); + + GL_Cull( faceCull ); +} + +/* +================ +R_RenderMeshGLSLProgrammed +================ +*/ +static void R_RenderMeshGLSLProgrammed( void ) +{ + const ref_stage_t *pass = ( ref_stage_t * )r_accumPasses[0]; + + switch( pass->program_type ) + { + case PROGRAM_TYPE_MATERIAL: + R_RenderMeshGLSL_Material(); + break; + case PROGRAM_TYPE_DISTORTION: + R_RenderMeshGLSL_Distortion(); + break; + case PROGRAM_TYPE_SHADOWMAP: + R_RenderMeshGLSL_Shadowmap(); + break; + case PROGRAM_TYPE_OUTLINE: + R_RenderMeshGLSL_Outline (); + break; + default: + MsgDev( D_WARN, "Unknown GLSL program type %i\n", pass->program_type ); + break; + } +} + +/* +================ +R_RenderAccumulatedPasses +================ +*/ +static void R_RenderAccumulatedPasses( void ) +{ + const ref_stage_t *pass = r_accumPasses[0]; + + R_CleanUpTextureUnits( r_numAccumPasses ); + + if( pass->program ) + { + r_numAccumPasses = 0; + R_RenderMeshGLSLProgrammed(); + return; + } + if( pass->flags & SHADERSTAGE_DLIGHT ) + { + r_numAccumPasses = 0; + R_AddDynamicLights( r_currentDlightBits, r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); + return; + } + if( pass->flags & SHADERSTAGE_STENCILSHADOW ) + { + r_numAccumPasses = 0; + R_PlanarShadowPass( r_currentShaderState | ( pass->glState & r_currentShaderPassMask )); + return; + } + + if( r_numAccumPasses == 1 ) + R_RenderMeshGeneric(); + else if( GL_Support( R_COMBINE_EXT )) + R_RenderMeshCombined(); + else + R_RenderMeshMultitextured(); + + r_numAccumPasses = 0; +} + +/* +================ +R_AccumulatePass +================ +*/ +static void R_AccumulatePass( ref_stage_t *pass ) +{ + bool accumulate, renderNow; + const ref_stage_t *prevPass; + + // for depth texture we render light's view to, ignore passes that do not write into depth buffer + if( ( RI.params & RP_SHADOWMAPVIEW ) && !( pass->glState & GLSTATE_DEPTHWRITE )) + return; + + // see if there are any free texture units + renderNow = ( pass->flags & ( SHADERSTAGE_DLIGHT|SHADERSTAGE_STENCILSHADOW ) ) || pass->program; + accumulate = ( r_numAccumPasses < glConfig.max_texture_units ) && !renderNow; + + if( accumulate ) + { + if( !r_numAccumPasses ) + { + r_accumPasses[r_numAccumPasses++] = pass; + return; + } + + // ok, we've got several passes, diff against the previous + prevPass = r_accumPasses[r_numAccumPasses-1]; + + // see if depthfuncs and colors are good + if( + (( prevPass->glState ^ pass->glState ) & GLSTATE_DEPTHFUNC_EQ ) || + ( pass->glState & GLSTATE_ALPHAFUNC ) || + ( pass->rgbGen.type != RGBGEN_IDENTITY ) || + ( pass->alphaGen.type != ALPHAGEN_IDENTITY ) || + ( ( prevPass->glState & GLSTATE_ALPHAFUNC ) && !( pass->glState & GLSTATE_DEPTHFUNC_EQ )) + ) + accumulate = false; + + // see if blendmodes are good + if( accumulate ) + { + int mode, prevMode; + + mode = R_ShaderpassBlendmode( pass->flags ); + if( mode ) + { + prevMode = R_ShaderpassBlendmode( prevPass->flags ); + + if( GL_Support( R_COMBINE_EXT )) + { + if( prevMode == GL_REPLACE ) + accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : true; + else if( prevMode == GL_ADD ) + accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT ); + else if( prevMode == GL_MODULATE ) + accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE ); + else + accumulate = false; + } + else /* if( GL_Support( R_ARB_MULTITEXTURE ))*/ + { + if( prevMode == GL_REPLACE ) + accumulate = ( mode == GL_ADD ) ? GL_Support( R_TEXTURE_ENV_ADD_EXT ) : ( mode != GL_DECAL ); + else if( prevMode == GL_ADD ) + accumulate = ( mode == GL_ADD ) && GL_Support( R_TEXTURE_ENV_ADD_EXT ); + else if( prevMode == GL_MODULATE ) + accumulate = ( mode == GL_MODULATE || mode == GL_REPLACE ); + else + accumulate = false; + } + } + else + { + accumulate = false; + } + } + } + + // no, failed to accumulate + if( !accumulate ) + { + if( r_numAccumPasses ) + R_RenderAccumulatedPasses(); + } + + r_accumPasses[r_numAccumPasses++] = pass; + if( renderNow ) + R_RenderAccumulatedPasses(); +} + +/* +================ +R_SetupLightmapMode +================ +*/ +void R_SetupLightmapMode( void ) +{ + r_lightmapPasses[0].tcgen = TCGEN_LIGHTMAP; + r_lightmapPasses[0].rgbGen.type = RGBGEN_IDENTITY; + r_lightmapPasses[0].alphaGen.type = ALPHAGEN_IDENTITY; + r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE; + r_lightmapPasses[0].glState &= ~( GLSTATE_ALPHAFUNC|GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK|GLSTATE_DEPTHFUNC_EQ ); + r_lightmapPasses[0].flags |= SHADERSTAGE_LIGHTMAP|SHADERSTAGE_NOCOLORARRAY|SHADERSTAGE_BLEND_MODULATE; +// r_lightmapPasses[0].glState |= GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ZERO; + if( r_lightmap->integer ) r_lightmapPasses[0].glState |= GLSTATE_DEPTHWRITE; +} + +/* +================ +R_RenderMeshBuffer +================ +*/ +void R_RenderMeshBuffer( const meshbuffer_t *mb ) +{ + int i; + msurface_t *surf; + ref_stage_t *pass; + mfog_t *fog; + + if( !r_backacc.numVerts || !r_backacc.numElems ) + { + R_ClearArrays(); + return; + } + + surf = mb->infokey > 0 ? &r_worldbrushmodel->surfaces[mb->infokey-1] : NULL; + if( surf ) + r_superLightStyle = &r_superLightStyles[surf->superLightStyle]; + else + r_superLightStyle = NULL; + r_currentMeshBuffer = mb; + + MB_NUM2SHADER( mb->shaderkey, r_currentShader ); + + if( glState.in2DMode ) + { + r_currentShaderTime = Sys_DoubleTime(); + } + else + { + r_currentShaderTime = (double)RI.refdef.time; + if( RI.currententity ) + { + r_currentShaderTime -= (double)RI.currententity->shaderTime; + if( r_currentShaderTime < 0 ) r_currentShaderTime = 0; + } + } + + if( !r_triangleOutlines ) + R_SetShaderState(); + + if( r_currentShader->numDeforms ) + R_DeformVertices(); + + if( r_features & MF_KEEPLOCK ) + r_backacc.c_totalKeptLocks++; + else + R_UnlockArrays(); + + if( r_triangleOutlines ) + { + R_LockArrays( r_backacc.numVerts ); + + if( RI.params & RP_TRISOUTLINES ) + R_DrawTriangles(); + if( RI.params & RP_SHOWNORMALS ) + R_DrawNormals(); + + R_ClearArrays(); + return; + } + + // extract the fog volume number from sortkey + if( !r_worldmodel ) + fog = NULL; + else + MB_NUM2FOG( mb->sortkey, fog ); + if( fog && !fog->shader ) + fog = NULL; + + // can we fog the geometry with alpha texture? + r_texFog = ( fog && ( ( r_currentShader->sort <= SORT_ALPHATEST && + ( r_currentShader->flags & (SHADER_DEPTHWRITE|SHADER_SKYPARMS))) || r_currentShader->fog_dist ) ) ? fog : NULL; + + // check if the fog volume is present but we can't use alpha texture + r_colorFog = ( fog && !r_texFog ) ? fog : NULL; + + if( r_currentShader->type == SHADER_FLARE ) + r_currentDlightBits = 0; + else + r_currentDlightBits = surf ? mb->dlightbits : 0; + + r_currentShadowBits = mb->shadowbits & RI.shadowBits; + + R_LockArrays( r_backacc.numVerts ); + + // accumulate passes for dynamic merging + for( i = 0, pass = r_currentShader->stages; i < r_currentShader->num_stages; i++, pass++ ) + { + if( !pass->program ) + { + if( pass->flags & SHADERSTAGE_LIGHTMAP ) + { + int j, k, l, u; + + // no valid lightmaps, goodbye + if( !r_superLightStyle || r_superLightStyle->lightmapNum[0] < 0 || r_superLightStyle->lightmapStyles[0] == 255 ) + continue; + + // try to apply lightstyles + if(( !( pass->glState & (GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK)) || ( pass->flags & SHADERSTAGE_BLEND_MODULATE )) && ( pass->rgbGen.type == RGBGEN_IDENTITY ) && ( pass->alphaGen.type == ALPHAGEN_IDENTITY )) + { + vec3_t colorSum, color; + + // the first pass is always GL_MODULATE or GL_REPLACE + // other passes are GL_ADD + r_lightmapPasses[0] = *pass; + + for( j = 0, l = 0, u = 0; j < LM_STYLES && r_superLightStyle->lightmapStyles[j] != 255; j++ ) + { + VectorCopy( r_lightStyles[r_superLightStyle->lightmapStyles[j]].rgb, colorSum ); + VectorClear( color ); + + for( ; ; l++ ) + { + for( k = 0; k < 3; k++ ) + { + colorSum[k] -= color[k]; + color[k] = bound( 0, colorSum[k], 1 ); + } + + if( l ) + { + if( !color[0] && !color[1] && !color[2] ) + break; + if( l == MAX_TEXTURE_UNITS+1 ) + r_lightmapPasses[0] = r_lightmapPasses[1]; + u = l % ( MAX_TEXTURE_UNITS+1 ); + } + + if( VectorCompare( color, colorWhite ) ) + { + r_lightmapPasses[u].rgbGen.type = RGBGEN_IDENTITY; + } + else + { + if( !l ) + { + r_lightmapPasses[0].flags &= ~SHADERSTAGE_BLENDMODE; + r_lightmapPasses[0].flags |= SHADERSTAGE_BLEND_MODULATE; + } + r_lightmapPasses[u].rgbGen.type = RGBGEN_CONST; + VectorCopy( color, r_lightmapPasses[u].rgbGen.args ); + } + + if( r_lightmap->integer && !l ) + R_SetupLightmapMode(); + R_AccumulatePass( &r_lightmapPasses[u] ); + r_lightmapStyleNum[r_numAccumPasses - 1] = j; + } + } + } + else + { + if( r_lightmap->integer ) + { + R_SetupLightmapMode(); + pass = r_lightmapPasses; + } + R_AccumulatePass( pass ); + r_lightmapStyleNum[r_numAccumPasses - 1] = 0; + } + continue; + } + else if( r_lightmap->integer && ( r_currentShader->flags & SHADER_HASLIGHTMAP )) + continue; + if(( pass->flags & SHADERSTAGE_PORTALMAP ) && !( RI.params & RP_PORTALCAPTURED )) + continue; + if(( pass->flags & SHADERSTAGE_DETAIL ) && !r_detailtextures->integer ) + continue; + if(( pass->flags & SHADERSTAGE_DLIGHT ) && !r_currentDlightBits ) + continue; + } + + R_AccumulatePass( pass ); + } + + // accumulate dynamic lights pass and fog pass if any + if( r_currentDlightBits && !( r_currentShader->flags & SHADER_NO_MODULATIVE_DLIGHTS )) + { + if( !r_lightmap->integer || !( r_currentShader->flags & SHADER_HASLIGHTMAP )) + R_AccumulatePass( &r_dlightsPass ); + } + + if( r_currentShadowBits && ( r_currentShader->sort >= SORT_OPAQUE ) && ( r_currentShader->sort <= SORT_ALPHATEST )) + R_AccumulatePass( &r_GLSLpasses[3] ); + + if( GL_Support( R_SHADER_GLSL100_EXT ) && RI.currententity && RI.currententity->outlineHeight && r_outlines_scale->value > 0 + && ( r_currentShader->sort == SORT_OPAQUE ) && ( r_currentShader->flags & SHADER_CULL_FRONT ) ) + R_AccumulatePass( &r_GLSLpassOutline ); + + if( r_texFog && r_texFog->shader ) + { + r_fogPass.textures[0] = tr.fogTexture; + if( !r_currentShader->num_stages || r_currentShader->fog_dist || ( r_currentShader->flags & SHADER_SKYPARMS ) ) + r_fogPass.glState &= ~GLSTATE_DEPTHFUNC_EQ; + else r_fogPass.glState |= GLSTATE_DEPTHFUNC_EQ; + R_AccumulatePass( &r_fogPass ); + } + + // flush any remaining passes + if( r_numAccumPasses ) + R_RenderAccumulatedPasses(); + + R_ClearArrays(); + + pglMatrixMode( GL_MODELVIEW ); +} + +/* +================ +R_BackendCleanUpTextureUnits +================ +*/ +void R_BackendCleanUpTextureUnits( void ) +{ + R_CleanUpTextureUnits( 1 ); + + GL_LoadIdentityTexMatrix(); + pglMatrixMode( GL_MODELVIEW ); + + GL_DisableAllTexGens(); + GL_SetTexCoordArrayMode( 0 ); +} + +/* +================ +R_BackendSetPassMask +================ +*/ +void R_BackendSetPassMask( int mask ) +{ + r_currentShaderPassMask = mask; +} + +/* +================ +R_BackendResetPassMask +================ +*/ +void R_BackendResetPassMask( void ) +{ + r_currentShaderPassMask = GLSTATE_MASK; +} + +/* +================ +R_BackendBeginTriangleOutlines +================ +*/ +void R_BackendBeginTriangleOutlines( void ) +{ + r_triangleOutlines = true; + pglColor4fv( colorWhite ); + + GL_Cull( 0 ); + GL_SetState( GLSTATE_NO_DEPTH_TEST ); + pglDisable( GL_TEXTURE_2D ); + pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); +} + +/* +================ +R_BackendEndTriangleOutlines +================ +*/ +void R_BackendEndTriangleOutlines( void ) +{ + r_triangleOutlines = false; + pglColor4fv( colorWhite ); + GL_SetState( 0 ); + pglEnable( GL_TEXTURE_2D ); + pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); +} + +/* +================ +R_SetColorForOutlines +================ +*/ +static _inline void R_SetColorForOutlines( void ) +{ + int type = r_currentMeshBuffer->sortkey & 3; + + switch( type ) + { + case MB_MODEL: + if( r_currentMeshBuffer->infokey < 0 ) + pglColor4fv( colorRed ); + else + pglColor4fv( colorWhite ); + break; + case MB_SPRITE: + pglColor4fv( colorBlue ); + break; + case MB_POLY: + pglColor4fv( colorGreen ); + break; + } +} + +/* +================ +R_DrawTriangles +================ +*/ +static void R_DrawTriangles( void ) +{ + if( r_showtris->integer == 2 ) + R_SetColorForOutlines(); + + if( GL_Support( R_DRAW_RANGEELEMENTS_EXT )) + pglDrawRangeElementsEXT( GL_TRIANGLES, 0, r_backacc.numVerts, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); + else pglDrawElements( GL_TRIANGLES, r_backacc.numElems, GL_UNSIGNED_INT, elemsArray ); +} + +/* +================ +R_DrawNormals +================ +*/ +static void R_DrawNormals( void ) +{ + unsigned int i; + + if( r_shownormals->integer == 2 ) + R_SetColorForOutlines(); + + pglBegin( GL_LINES ); + for( i = 0; i < r_backacc.numVerts; i++ ) + { + pglVertex3fv( vertsArray[i] ); + pglVertex3f( vertsArray[i][0] + normalsArray[i][0], vertsArray[i][1] + normalsArray[i][1], vertsArray[i][2] + normalsArray[i][2] ); + } + pglEnd(); +} + +static void R_DrawLine( int color, int numpoints, const float *points, const int *elements ) +{ + int i = numpoints - 1; + vec3_t p0, p1; + + VectorSet( p0, points[i*3+0], points[i*3+1], points[i*3+2] ); + if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p0 ); + + for( i = 0; i < numpoints; i++ ) + { + VectorSet( p1, points[i*3+0], points[i*3+1], points[i*3+2] ); + if( r_physbdebug->integer == 1 ) ConvertPositionToGame( p1 ); + + pglColor4fv( UnpackRGBA( color )); + pglVertex3fv( p0 ); + pglVertex3fv( p1 ); + + VectorCopy( p1, p0 ); + } +} + +/* +================ +R_DrawPhysDebug +================ +*/ +void R_DrawPhysDebug( void ) +{ + if( r_physbdebug->integer ) + { + // physic debug + pglLoadMatrixf( RI.worldviewMatrix ); + pglBegin( GL_LINES ); + ri.ShowCollision( R_DrawLine ); + pglEnd(); + } +} \ No newline at end of file diff --git a/render/r_bloom.c b/render/r_bloom.c index 8cf0a23c..d2c65afd 100644 --- a/render/r_bloom.c +++ b/render/r_bloom.c @@ -377,7 +377,6 @@ static void R_Bloom_GeneratexDiamonds( void ) scale = r_bloom_intensity->value * 0.5f; break; default: -// case 8: k = 4; diamond = &Diamond8x[0][0]; scale = r_bloom_intensity->value * 0.3f; diff --git a/render/r_image.c b/render/r_image.c index 4b98c19f..834887ea 100644 --- a/render/r_image.c +++ b/render/r_image.c @@ -276,10 +276,6 @@ void R_SetTextureParameters( void ) for( i = 0, texture = r_textures; i < r_numTextures; i++, texture++ ) { if( !texture->texnum ) continue; // free slot - - - continue; - GL_Bind( GL_TEXTURE0, texture ); if( texture->flags & TF_DEPTHMAP ) @@ -558,13 +554,10 @@ static void R_TextureFormat( texture_t *tex, bool compress ) } } -void R_RoundImageDimensions( int *width, int *height, int *depth ) +void R_RoundImageDimensions( int *width, int *height, int *depth, bool force ) { int scaledWidth, scaledHeight, scaledDepth; - if( GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - return; // nothing to resample - if( *depth > 1 && !GL_Support( R_TEXTURE_3D_EXT )) return; // nothing to resample @@ -572,10 +565,13 @@ void R_RoundImageDimensions( int *width, int *height, int *depth ) scaledHeight = *height; scaledDepth = *depth; - // find nearest power of two, rounding down if desired - scaledWidth = NearestPOW( scaledWidth, gl_round_down->integer ); - scaledHeight = NearestPOW( scaledHeight, gl_round_down->integer ); - scaledDepth = NearestPOW( scaledDepth, gl_round_down->integer ); + if( force || !GL_Support( R_ARB_TEXTURE_NPOT_EXT )) + { + // find nearest power of two, rounding down if desired + scaledWidth = NearestPOW( scaledWidth, gl_round_down->integer ); + scaledHeight = NearestPOW( scaledHeight, gl_round_down->integer ); + scaledDepth = NearestPOW( scaledDepth, gl_round_down->integer ); + } if( image_desc.tflags & TF_SKYSIDE ) { @@ -874,7 +870,7 @@ bool R_GetPixelFormat( const char *name, rgbdata_t *pic, uint tex_flags ) else image_desc.texType = TEX_GENERIC; // calc immediate buffers - R_RoundImageDimensions( &w, &h, &d ); + R_RoundImageDimensions( &w, &h, &d, false ); image_desc.source = Mem_Alloc( r_imagepool, s * 4 ); // source buffer image_desc.scaled = Mem_Alloc( r_imagepool, w * h * d * 4 ); // scaled buffer @@ -1541,6 +1537,37 @@ static rgbdata_t *R_IncludeDepthmap( rgbdata_t *in1, rgbdata_t *in2 ) return in1; } +/* +================ +R_ClearPixels + +clear specified area: color or alpha +================ +*/ +static rgbdata_t *R_ClearPixels( rgbdata_t *in, bool clearAlpha ) +{ + int i; + byte *pic; + + // make sure what we processing RGBA images + in = R_ForceImageToRGBA( in ); + pic = in->buffer; + + if( clearAlpha ) + { + for( i = 0; i < in->width * in->height && in->flags & IMAGE_HAS_ALPHA; i++ ) + pic[(i<<2)+3] = 0xFF; + } + else + { + // clear color or greyscale image otherwise + for( i = 0; i < in->width * in->height; i++ ) + pic[(i<<2)+0] = pic[(i<<2)+1] = pic[(i<<2)+2] = 0xFF; + } + return in; +} + + /* ================= R_ParseAdd @@ -2528,6 +2555,7 @@ static rgbdata_t *R_ParseDepthmap( script_t *script, int *samples, texFlags_t *f return NULL; } + *samples = 3; pic2 = R_LoadImage( script, token.string, NULL, 0, &samples2, flags ); if( !pic2 ) return pic1; // don't free normalmap @@ -2558,6 +2586,65 @@ static rgbdata_t *R_ParseDepthmap( script_t *script, int *samples, texFlags_t *f return R_IncludeDepthmap( pic1, pic2 ); } +/* +================= +R_ParseClearPixels +================= +*/ +static rgbdata_t *R_ParseClearPixels( script_t *script, int *samples, texFlags_t *flags ) +{ + token_t token; + rgbdata_t *pic; + bool clearAlpha; + + Com_ReadToken( script, 0, &token ); + if( com.stricmp( token.string, "(" )) + { + MsgDev( D_WARN, "expected '(', found '%s' instead for 'clearPixels'\n", token.string ); + return NULL; + } + + if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &token )) + { + MsgDev( D_WARN, "missing parameters for 'clearPixels'\n" ); + return NULL; + } + + pic = R_LoadImage( script, token.string, NULL, 0, samples, flags ); + if( !pic ) return NULL; + + Com_ReadToken( script, 0, &token ); + if( !com.stricmp( token.string, "alpha" )) + { + Com_ReadToken( script, 0, &token ); + clearAlpha = true; + } + else if( !com.stricmp( token.string, "color" )) + { + Com_ReadToken( script, 0, &token ); + clearAlpha = false; + } + else if( !com.stricmp( token.string, ")" )) + { + Com_SaveToken( script, &token ); + clearAlpha = false; // clear color as default + } + else Com_ReadToken( script, 0, &token ); // skip unknown token + + if( com.stricmp( token.string, ")" )) + { + MsgDev( D_WARN, "expected ')', found '%s' instead for 'clearPixels'\n", token.string ); + FS_FreeImage( pic ); + return NULL; + } + + *samples = clearAlpha ? 3 : 1; + if( clearAlpha ) *flags &= ~TF_ALPHA; + *flags &= ~TF_INTENSITY; + + return R_ClearPixels( pic, clearAlpha ); +} + /* ================= R_LoadImage @@ -2595,6 +2682,8 @@ static rgbdata_t *R_LoadImage( script_t *script, const char *name, const byte *b return R_ParseSmoothNormals( script, samples, flags ); else if( !com.stricmp( name, "mergeDepthmap" )) return R_ParseDepthmap( script, samples, flags ); + else if( !com.stricmp( name, "clearPixels" )) + return R_ParseClearPixels( script, samples, flags ); else if( !com.stricmp( name, "Studio" )) return R_ParseStudioSkin( script, samples, flags ); else if( !com.stricmp( name, "Sprite" )) @@ -2661,7 +2750,15 @@ void GL_GenerateMipmaps( const byte *buffer, texture_t *tex, int side ) void GL_TexFilter( texture_t *tex ) { // set texture filter - if( tex->flags & TF_NOMIPMAP ) + if( tex->flags & TF_DEPTHMAP ) + { + pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter ); + pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter ); + + if( GL_Support( R_ANISOTROPY_EXT )) + pglTexParameterf( tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); + } + else if( tex->flags & TF_NOMIPMAP ) { pglTexParameteri( tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); pglTexParameteri( tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); @@ -2717,7 +2814,7 @@ static void R_UploadTexture( rgbdata_t *pic, texture_t *tex ) tex->width = tex->srcWidth; tex->height = tex->srcHeight; - R_RoundImageDimensions( &tex->width, &tex->height, &tex->depth ); + R_RoundImageDimensions( &tex->width, &tex->height, &tex->depth, false ); // check if it should be compressed if( !gl_compress_textures->integer || (tex->flags & TF_UNCOMPRESSED)) @@ -2734,7 +2831,6 @@ static void R_UploadTexture( rgbdata_t *pic, texture_t *tex ) case PF_DXT5: tex->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; break; default: dxtformat = false; break; } - pglGenTextures( 1, &tex->texnum ); GL_Bind( GL_TEXTURE0, tex ); @@ -3357,7 +3453,7 @@ static rgbdata_t *R_InitCoronaTexture( int *flags, int *samples ) R_InitScreenTexture ================== */ -static void R_InitScreenTexture( texture_t **texture, const char *name, int id, int screenWidth, int screenHeight, int size, int flags, int samples ) +static void R_InitScreenTexture( texture_t **ptr, const char *name, int id, int screenWidth, int screenHeight, int size, int flags, int samples ) { int limit; int width, height; @@ -3367,43 +3463,36 @@ static void R_InitScreenTexture( texture_t **texture, const char *name, int id, limit = glConfig.max_2d_texture_size; if( size ) limit = min( limit, size ); - if( GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - { - width = min( screenWidth, limit ); - height = min( screenHeight, limit ); - } - else - { - limit = min( limit, min( screenWidth, screenHeight )); - for( size = 2; size <= limit; size <<= 1 ); - width = height = size >> 1; - } + limit = min( limit, min( screenWidth, screenHeight )); + for( size = 2; size <= limit; size <<= 1 ); + width = height = size >> 1; - if( !( *texture ) || ( *texture )->width != width || ( *texture )->height != height ) + if( !(*ptr) || (*ptr)->width != width || (*ptr)->height != height ) { byte *data = NULL; - if( !*texture ) + if( !*ptr ) { - string uploadName; + string name; - com.snprintf( uploadName, sizeof( uploadName ), "***%s%i***", name, id ); + com.snprintf( name, sizeof( name ), "***%s%i***", name, id ); r_screen.width = width; r_screen.height = height; - r_screen.depth = r_screen.numMips = 1; r_screen.type = PF_RGB_24; r_screen.buffer = data; + r_screen.depth = r_screen.numMips = 1; r_screen.size = width * height * samples; - *texture = R_LoadTexture( uploadName, &r_screen, samples, flags ); + *ptr = R_LoadTexture( name, &r_screen, samples, flags ); return; } - GL_Bind( 0, *texture ); - ( *texture )->width = width; - ( *texture )->height = height; - R_Upload32( &data, width, height, flags, &( ( *texture )->width ), &( ( *texture )->height ), - &( ( *texture )->samples ), false ); + GL_Bind( 0, *ptr ); + (*ptr)->width = width; + (*ptr)->height = height; + R_RoundImageDimensions(&((*ptr)->width), &((*ptr)->height), &((*ptr)->depth), true ); + pglTexImage2D( GL_TEXTURE_2D, 0, (*ptr)->format, (*ptr)->width, (*ptr)->height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); + GL_TexFilter( *ptr ); } } @@ -3643,254 +3732,4 @@ void R_ShutdownImages( void ) r_numTextures = 0; tr.portaltexture1 = NULL; tr.portaltexture2 = NULL; -} - -// to be removed -/* -=============== -R_UploadFormat -=============== -*/ -static int R_UploadFormat( int samples, bool noCompress ) -{ - int bits = r_texturebits->integer; - - if( GL_Support( R_TEXTURE_COMPRESSION_EXT ) && !noCompress ) - { - if( samples == 3 ) - return GL_COMPRESSED_RGB_ARB; - return GL_COMPRESSED_RGBA_ARB; - } - - if( samples == 3 ) - { - if( bits == 16 ) - return GL_RGB5; - else if( bits == 32 ) - return GL_RGB8; - return GL_RGB; - } - - if( bits == 16 ) - return GL_RGBA4; - else if( bits == 32 ) - return GL_RGBA8; - return GL_RGBA; -} - -/* -=============== -R_Upload32 -=============== -*/ -void R_Upload32( byte **data, int width, int height, int flags, int *upload_width, int *upload_height, int *samples, bool subImage ) -{ - int i, c, comp, format; - int target, target2; - int numTextures; - uint *scaled = NULL; - int scaledWidth, scaledHeight; - - Com_Assert( samples == NULL ); - - if( GL_Support( R_ARB_TEXTURE_NPOT_EXT )) - { - scaledWidth = width; - scaledHeight = height; - } - else - { - for( scaledWidth = 1; scaledWidth < width; scaledWidth <<= 1 ); - for( scaledHeight = 1; scaledHeight < height; scaledHeight <<= 1 ); - } - - if( flags & TF_SKYSIDE ) - { - // let people sample down the sky textures for speed - scaledWidth >>= r_skymip->integer; - scaledHeight >>= r_skymip->integer; - } - else if( !( flags & TF_NOPICMIP ) ) - { - // let people sample down the world textures for speed - scaledWidth >>= r_picmip->integer; - scaledHeight >>= r_picmip->integer; - } - - // don't ever bother with > maxSize textures - if( flags & TF_CUBEMAP ) - { - numTextures = 6; - target = GL_TEXTURE_CUBE_MAP_ARB; - target2 = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; - scaledWidth = bound( 1, scaledWidth, glConfig.max_cubemap_texture_size ); - scaledHeight = bound( 1, scaledHeight, glConfig.max_cubemap_texture_size ); - } - else - { - numTextures = 1; - target = GL_TEXTURE_2D; - target2 = GL_TEXTURE_2D; - scaledWidth = bound( 1, scaledWidth, glConfig.max_2d_texture_size ); - scaledHeight = bound( 1, scaledHeight, glConfig.max_2d_texture_size ); - } - - if( upload_width ) - *upload_width = scaledWidth; - if( upload_height ) - *upload_height = scaledHeight; - - // scan the texture for any non-255 alpha - if( flags & ( TF_NORGB|TF_NOALPHA ) ) - { - byte *scan; - - if( flags & TF_NORGB ) - { - for( i = 0; i < numTextures && data[i]; i++ ) - { - scan = ( byte * )data[i]; - for( c = width * height; c > 0; c--, scan += 4 ) - scan[0] = scan[1] = scan[2] = 255; - } - } - else if( *samples == 4 ) - { - for( i = 0; i < numTextures && data[i]; i++ ) - { - scan = ( byte * )data[i] + 3; - for( c = width * height; c > 0; c--, scan += 4 ) - *scan = 255; - } - *samples = 3; - } - } - - if( flags & TF_DEPTHMAP ) - { - comp = GL_DEPTH_COMPONENT; - format = GL_DEPTH_COMPONENT; - } - else - { - comp = R_UploadFormat( *samples, flags & TF_UNCOMPRESSED ); - format = GL_RGBA; - } - - if( flags & TF_DEPTHMAP ) - { - pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureDepthFilter ); - pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureDepthFilter ); - - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameteri( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 ); - } - else if( !( flags & TF_NOMIPMAP ) ) - { - pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureMinFilter ); - pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); - - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_texture_anisotropy->value ); - } - else - { - pglTexParameteri( target, GL_TEXTURE_MIN_FILTER, r_textureMagFilter ); - pglTexParameteri( target, GL_TEXTURE_MAG_FILTER, r_textureMagFilter ); - - if( GL_Support( R_ANISOTROPY_EXT )) - pglTexParameterf( target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f ); - } - - // clamp if required - if( !( flags & TF_CLAMP ) ) - { - pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_REPEAT ); - pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_REPEAT ); - } - else if( GL_Support( R_CLAMPTOEDGE_EXT )) - { - pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - } - else - { - pglTexParameteri( target, GL_TEXTURE_WRAP_S, GL_CLAMP ); - pglTexParameteri( target, GL_TEXTURE_WRAP_T, GL_CLAMP ); - } - - if(( scaledWidth == width ) && ( scaledHeight == height ) && ( flags & TF_NOMIPMAP )) - { - if( subImage ) - { - for( i = 0; i < numTextures; i++, target2++ ) - pglTexSubImage2D( target2, 0, 0, 0, scaledWidth, scaledHeight, format, GL_UNSIGNED_BYTE, data[i] ); - } - else - { - for( i = 0; i < numTextures; i++, target2++ ) - pglTexImage2D( target2, 0, comp, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE, data[i] ); - } - } - else - { - bool driverMipmap = GL_Support( R_SGIS_MIPMAPS_EXT ) && !(flags & TF_CUBEMAP); - - for( i = 0; i < numTextures; i++, target2++ ) - { - unsigned int *mip; - - if( scaledWidth == width && scaledHeight == height && driverMipmap ) - { - mip = (uint *)(data[i]); - } - else - { - mip = NULL; - - // resample the texture - if( data[i] ) - { - R_ResampleTexture( data[i], width, height, scaledWidth, scaledHeight, false ); - mip = (uint *)image_desc.scaled; - } - } - - // automatic mipmaps generation - if( !( flags & TF_NOMIPMAP ) && mip && driverMipmap ) - pglTexParameteri( target2, GL_GENERATE_MIPMAP_SGIS, GL_TRUE ); - - if( subImage ) - pglTexSubImage2D( target2, 0, 0, 0, scaledWidth, scaledHeight, format, GL_UNSIGNED_BYTE, mip ); - else - pglTexImage2D( target2, 0, comp, scaledWidth, scaledHeight, 0, format, GL_UNSIGNED_BYTE, mip ); - - // mipmaps generation - if( !( flags & TF_NOMIPMAP ) && mip && !driverMipmap ) - { - int w, h; - int miplevel = 0; - - w = scaledWidth; - h = scaledHeight; - while( w > 1 || h > 1 ) - { - R_BuildMipMap( (byte *)mip, w, h, false ); - - w >>= 1; - h >>= 1; - if( w < 1 ) - w = 1; - if( h < 1 ) - h = 1; - miplevel++; - - if( subImage ) - pglTexSubImage2D( target2, miplevel, 0, 0, w, h, format, GL_UNSIGNED_BYTE, mip ); - else - pglTexImage2D( target2, miplevel, comp, w, h, 0, format, GL_UNSIGNED_BYTE, mip ); - } - } - } - } } \ No newline at end of file diff --git a/render/r_local.h b/render/r_local.h index fb0006d5..8f3819ec 100644 --- a/render/r_local.h +++ b/render/r_local.h @@ -76,11 +76,9 @@ typedef enum TF_DEPTHMAP = BIT(5), // custom texture filter used TF_INTENSITY = BIT(5), TF_ALPHA = BIT(6), - TF_NORGB = BIT(7), // QFusion legacy. convert to funcs? - TF_NOALPHA = BIT(8), - TF_SKYSIDE = BIT(9), - TF_CLAMP = BIT(10), - TF_NOMIPMAP = BIT(11), + TF_SKYSIDE = BIT(7), + TF_CLAMP = BIT(8), + TF_NOMIPMAP = BIT(9), } texFlags_t; #define TF_CINEMATIC ( TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP ) @@ -298,6 +296,7 @@ extern cvar_t *r_lerpmodels; extern cvar_t *r_ignorehwgamma; extern cvar_t *r_overbrightbits; extern cvar_t *r_mapoverbrightbits; +extern cvar_t *r_vertexbuffers; extern cvar_t *r_lefthand; extern cvar_t *r_physbdebug; extern cvar_t *r_check_errors; @@ -504,7 +503,6 @@ void R_TextureList_f( void ); void R_SetTextureParameters( void ); void R_ShowTextures( void ); -void R_Upload32( byte **data, int width, int height, int flags, int *upload_width, int *upload_height, int *samples, bool subImage ); texture_t *R_LoadTexture( const char *name, rgbdata_t *pic, int samples, texFlags_t flags ); texture_t *R_FindTexture( const char *name, const byte *buf, size_t size, texFlags_t flags ); @@ -668,8 +666,9 @@ msurface_t *R_TransformedTraceLine( trace_t *tr, const vec3_t start, const vec3_ // // r_register.c // -void R_Restart( void ); -void R_Shutdown( bool verbose ); +void R_NewMap( void ); +bool R_Init( bool full ); +void R_Shutdown( bool full ); // // r_opengl.c @@ -701,16 +700,6 @@ struct skinfile_s *R_SkinFile_Load( const char *name ); struct skinfile_s *R_RegisterSkinFile( const char *name ); ref_shader_t *R_FindShaderForSkinFile( const struct skinfile_s *skinfile, const char *meshname ); -// -// r_skm.c -// -bool R_CullSkeletalModel( ref_entity_t *e ); -void R_AddSkeletalModelToList( ref_entity_t *e ); -void R_DrawSkeletalModel( const meshbuffer_t *mb ); -float R_SkeletalModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs ); -int R_SkeletalGetBoneInfo( const ref_model_t *mod, int bonenum, char *name, size_t name_size, int *flags ); -void R_SkeletalGetBonePose( const ref_model_t *mod, int bonenum, int frame, bonepose_t *bonepose ); - // // r_warp.c // diff --git a/render/r_main.c b/render/r_main.c index b2b859c2..fd0678d0 100644 --- a/render/r_main.c +++ b/render/r_main.c @@ -691,7 +691,6 @@ static void R_PushCorona( const meshbuffer_t *mb ) R_PushMesh( &spr_mesh, MF_NOCULL | MF_TRIFAN | shader->features ); } -#ifdef QUAKE2_JUNK /* ================= R_PushSpriteModel @@ -709,7 +708,6 @@ bool R_PushSpriteModel( const meshbuffer_t *mb ) return R_PushSprite( mb, e->rotation, frame->origin_x, frame->origin_x - frame->width, frame->height - frame->origin_y, -frame->origin_y ); } -#endif /* ================= @@ -734,7 +732,6 @@ bool R_PushSpritePoly( const meshbuffer_t *mb ) return R_PushSprite( mb, e->rotation, -e->radius, e->radius, e->radius, -e->radius ); } -#ifdef QUAKE2_JUNK /* ================= R_AddSpriteModelToList @@ -775,7 +772,6 @@ static void R_AddSpriteModelToList( ref_entity_t *e ) if( mb ) mb->shaderkey |= ( bound( 1, 0x4000 - (unsigned int)dist, 0x4000 - 1 ) << 12 ); } -#endif /* ================= @@ -1005,13 +1001,15 @@ static void R_SetupFrustum( void ) for( i = 0; i < 4; i++ ) { + RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( RI.viewOrigin, RI.frustum[i].normal ); - PlaneClassify( &RI.frustum[i] ); + RI.frustum[i].signbits = SignbitsForPlane( &RI.frustum[i] ); } VectorMA( RI.viewOrigin, RI.farClip, RI.vpn, farPoint ); + RI.frustum[i].type = PLANE_NONAXIAL; RI.frustum[i].dist = DotProduct( farPoint, RI.frustum[i].normal ); - PlaneClassify( &RI.frustum[i] ); + RI.frustum[i].signbits = SignbitsForPlane( &RI.frustum[i] ); } /* @@ -1362,10 +1360,8 @@ static void R_CategorizeEntities( void ) if( !( RI.currententity->renderfx & ( RF_NOSHADOW|RF_PLANARSHADOW ) ) ) R_AddShadowCaster( RI.currententity ); // build groups and mark shadow casters break; -#ifdef QUAKE2_JUNK case mod_sprite: break; -#endif default: Host_Error( "%s: bad modeltype\n", RI.currentmodel->name ); break; @@ -1405,18 +1401,15 @@ static void R_CullEntities( void ) culled = R_CullAliasModel( e ); break; case mod_studio: - culled = R_CullSkeletalModel( e ); + culled = true; break; case mod_brush: culled = R_CullBrushModel( e ); break; -#ifdef QUAKE2_JUNK case mod_sprite: culled = false; break; -#endif - default: - break; + default: break; } break; case RT_SPRITE: @@ -1517,16 +1510,12 @@ add: R_AddAliasModelToList( e ); break; case mod_studio: - R_AddSkeletalModelToList( e ); break; -#ifdef QUAKE2_JUNK case mod_sprite: if( !shadowmap ) R_AddSpriteModelToList( e ); break; -#endif - default: - break; + default: break; } break; case RT_SPRITE: @@ -2390,19 +2379,21 @@ bool R_AddEntityToScene( edict_t *pRefEntity, int ed_type, float lerpfrac ) return result; } -bool R_AddDynamicLight( vec3_t org, vec3_t color, float intensity ) +bool R_AddDynamicLight( vec3_t org, vec3_t color, float intensity, shader_t handle ) { - dlight_t *dl; + dlight_t *dl; + ref_shader_t *shader; if(( r_numDlights >= MAX_DLIGHTS ) || (intensity == 0) || ( VectorIsNull( color ))) return false; - + if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle])->name) + shader = NULL; dl = &r_dlights[r_numDlights++]; VectorCopy( org, dl->origin ); VectorCopy( color, dl->color ); dl->intensity = intensity * DLIGHT_SCALE; - dl->shader = NULL; // FIXME; + dl->shader = shader; R_LightBounds( org, dl->intensity, dl->mins, dl->maxs ); diff --git a/render/r_math.c b/render/r_math.c index 9b535c49..77ecc14b 100644 --- a/render/r_math.c +++ b/render/r_math.c @@ -295,6 +295,37 @@ void AdjustFov( float *fov_x, float *fov_y, float width, float height, bool lock else *fov_y = y; } +/* +================= +SignbitsForPlane + +fast box on planeside test +================= +*/ +int SignbitsForPlane( const cplane_t *out ) +{ + int bits, i; + + for( i = bits = 0; i < 3; i++ ) + if( out->normal[i] < 0.0f ) bits |= 1<= 1.0f ) return PLANE_X; + if( normal[1] >= 1.0f ) return PLANE_Y; + if( normal[2] >= 1.0f ) return PLANE_Z; + return PLANE_NONAXIAL; +} + + /* ================= PlaneFromPoints @@ -309,7 +340,4 @@ void PlaneFromPoints( vec3_t verts[3], cplane_t *plane ) CrossProduct( v2, v1, plane->normal ); VectorNormalize( plane->normal ); plane->dist = DotProduct( verts[0], plane->normal ); - - // FIXME: needs to a plane classify ? - //PlaneClassify( plane ); } \ No newline at end of file diff --git a/render/r_math.h b/render/r_math.h index d9878718..fd9a20f9 100644 --- a/render/r_math.h +++ b/render/r_math.h @@ -26,7 +26,7 @@ extern const mat4x4_t mat4x4_identity; void Matrix4_Identity( mat4x4_t m ); void Matrix4_Copy( const mat4x4_t m1, mat4x4_t m2 ); -bool Matrix4_Compare( const mat4x4_t m1, const mat4x4_t m2 ); +bool Matrix4_Compare( const mat4x4_t m1, const mat4x4_t m2 ); void Matrix4_Multiply( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out ); void Matrix4_MultiplyFast( const mat4x4_t m1, const mat4x4_t m2, mat4x4_t out ); void Matrix4_Rotate( mat4x4_t m, vec_t angle, vec_t x, vec_t y, vec_t z ); @@ -46,5 +46,7 @@ void Matrix4_Stretch2D( mat4x4_t m, vec_t s, vec_t t ); float CalcFov( float fov_x, float width, float height ); void AdjustFov( float *fov_x, float *fov_y, float width, float height, bool lock_x ); void PlaneFromPoints( vec3_t verts[3], cplane_t *plane ); +int SignbitsForPlane( const cplane_t *out ); +int PlaneTypeForNormal( const vec3_t normal ); #endif /*__R_MATH_H__*/ diff --git a/render/r_mesh.c b/render/r_mesh.c index ed17118d..11767f58 100644 --- a/render/r_mesh.c +++ b/render/r_mesh.c @@ -174,6 +174,107 @@ static void R_ISortMeshBuffers( meshbuffer_t *meshes, int num_meshes ) } } +/* +======================================================================= + +VERTEX BUFFERS + +======================================================================= +*/ +/* +================= +R_UpdateVertexBuffer +================= +*/ +void R_UpdateVertexBuffer( ref_buffer_t *vertexBuffer, const void *data, size_t size ) +{ + if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) + { + vertexBuffer->pointer = (char *)data; + return; + } + + if( !r_vertexbuffers->integer ) + { + vertexBuffer->pointer = (char *)data; + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); + return; + } + + vertexBuffer->pointer = NULL; + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum ); + pglBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0, size, data ); +} + +/* +================= +R_AllocVertexBuffer +================= +*/ +ref_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage ) +{ + ref_buffer_t *vertexBuffer; + + if( tr.numVertexBufferObjects == MAX_VERTEX_BUFFER_OBJECTS ) + Host_Error( "RB_AllocVertexBuffer: MAX_VERTEX_BUFFER_OBJECTS limit exceeds\n" ); + + vertexBuffer = &tr.vertexBufferObjects[tr.numVertexBufferObjects++]; + + vertexBuffer->pointer = NULL; + vertexBuffer->size = size; + vertexBuffer->usage = usage; + + if(!GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) + return vertexBuffer; + + pglGenBuffersARB( 1, &vertexBuffer->bufNum ); + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->bufNum ); + pglBufferDataARB( GL_ARRAY_BUFFER_ARB, vertexBuffer->size, NULL, vertexBuffer->usage ); + + return vertexBuffer; +} + +/* +================= +R_InitVertexBuffers +================= +*/ +void R_InitVertexBuffers( void ) +{ + int i; + + tr.vertexBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB ); + tr.colorsBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( rgba_t ), GL_STREAM_DRAW_ARB ); + tr.normalBuffer = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB ); + for( i = 0; i < MAX_TEXTURE_UNITS; i++ ) + tr.tcoordBuffer[i] = R_AllocVertexBuffer( MAX_ARRAY_VERTS * sizeof( vec4_t ), GL_STREAM_DRAW_ARB ); +} + +/* +================= +R_ShutdownVertexBuffers +================= +*/ +void R_ShutdownVertexBuffers( void ) +{ + ref_buffer_t *vertexBuffer; + int i; + + if( !GL_Support( R_ARB_VERTEX_BUFFER_OBJECT_EXT )) + { + Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects )); + tr.numVertexBufferObjects = 0; + return; + } + + pglBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); + for( i = 0, vertexBuffer = tr.vertexBufferObjects; i < tr.numVertexBufferObjects; i++, vertexBuffer++ ) + pglDeleteBuffersARB( 1, &vertexBuffer->bufNum ); + + Mem_Set( tr.vertexBufferObjects, 0, sizeof( tr.vertexBufferObjects )); + tr.numVertexBufferObjects = 0; +} + /* ================= R_ReAllocMeshList @@ -364,7 +465,6 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm case mod_alias: R_DrawAliasModel( mb ); break; -#ifdef QUAKE2_JUNK case mod_sprite: R_PushSpriteModel( mb ); @@ -372,9 +472,7 @@ static void R_BatchMeshBuffer( const meshbuffer_t *mb, const meshbuffer_t *nextm R_TranslateForEntity( RI.currententity ); R_RenderMeshBuffer( mb ); break; -#endif case mod_studio: - R_DrawSkeletalModel( mb ); break; default: Com_Assert( 1 ); // shut up compiler diff --git a/render/r_model.c b/render/r_model.c index 81c0d22e..82fdf7a4 100644 --- a/render/r_model.c +++ b/render/r_model.c @@ -88,7 +88,6 @@ static int loadmodel_numshaderrefs; static mshaderref_t *loadmodel_shaderrefs; void Mod_LoadAliasMD3Model( ref_model_t *mod, ref_model_t *parent, const void *buffer ); -void Mod_LoadSkeletalModel( ref_model_t *mod, ref_model_t *parent, const void *buffer ); void Mod_LoadBrushModel( ref_model_t *mod, ref_model_t *parent, const void *buffer ); ref_model_t *Mod_LoadModel( ref_model_t *mod, bool crash ); @@ -102,8 +101,7 @@ static byte *mod_mempool; static modelformatdescriptor_t mod_supportedformats[] = { -{ IDMD3HEADER, MD3_ALIAS_MAX_LODS, Mod_LoadAliasMD3Model }, // Quake III Arena .md3 models -{ SKMHEADER, SKM_MAX_LODS, Mod_LoadSkeletalModel }, // Skeletal models +{ ALIASMODHEADER, MD3_ALIAS_MAX_LODS, Mod_LoadAliasMD3Model }, // Quake III Arena .md3 models { IDBSPMODHEADER, 0, Mod_LoadBrushModel }, // Quake III Arena .bsp models { RBBSPMODHEADER, 0, Mod_LoadBrushModel }, // SOF2 and JK2 .bsp models { QFBSPMODHEADER, 0, Mod_LoadBrushModel }, // QFusion .bsp models @@ -422,7 +420,7 @@ ref_model_t *Mod_ForName( const char *name, bool crash ) FS_StripExtension( shortname ); // load level-of-detail models - for( i = mod->numlods = 0; i < descr->maxLods; i++ ) + for( mod->numlods = i = 0; i < descr->maxLods; i++ ) { com.snprintf( lodname, sizeof( lodname ), "%s_%i.%s", shortname, i+1, ext ); buf = (uint *)FS_LoadFile( lodname, NULL ); @@ -1322,7 +1320,7 @@ static void Mod_LoadFogs( const lump_t *l, const lump_t *brLump, const lump_t *b for( i = 0; i < count; i++, in++, out++ ) { - out->shader = R_RegisterShader( in->shader ); + out->shader = R_LoadShader( in->shader, SHADER_TEXTURE, false, 0, SHADER_INVALID ); p = LittleLong( in->brushnum ); if( p == -1 ) continue; @@ -2037,63 +2035,6 @@ void Mod_LoadBrushModel( ref_model_t *mod, ref_model_t *parent, const void *buff else bmodel->numsubmodels = 0; } } - -#ifdef QUAKE2_JUNK - -/* -============================================================================== - -SPRITE MODELS - -============================================================================== -*/ - -/* -================= -Mod_LoadSpriteModel -================= -*/ -void Mod_LoadSpriteModel( ref_model_t *mod, ref_model_t *parent, void *buffer ) -{ - int i; - dsprite_t *sprin; - smodel_t *sprout; - dsprframe_t *sprinframe; - sframe_t *sproutframe; - - sprin = (dsprite_t *)buffer; - - if( LittleLong( sprin->version ) != SPRITE_VERSION ) - Host_Error( ERR_DROP, "%s has wrong version number (%i should be %i)", - mod->name, LittleLong( sprin->version ), SPRITE_VERSION ); - - mod->extradata = sprout = Mod_Malloc( mod, sizeof( smodel_t ) ); - sprout->numframes = LittleLong( sprin->numframes ); - - sprinframe = sprin->frames; - sprout->frames = sproutframe = Mod_Malloc( mod, sizeof( sframe_t ) * sprout->numframes ); - - mod->radius = 0; - ClearBounds( mod->mins, mod->maxs ); - - // byte swap everything - for( i = 0; i < sprout->numframes; i++, sprinframe++, sproutframe++ ) - { - sproutframe->width = LittleLong( sprinframe->width ); - sproutframe->height = LittleLong( sprinframe->height ); - sproutframe->origin_x = LittleLong( sprinframe->origin_x ); - sproutframe->origin_y = LittleLong( sprinframe->origin_y ); - sproutframe->shader = R_RegisterPic( sprinframe->name ); - sproutframe->radius = sqrt( sproutframe->width * sproutframe->width + sproutframe->height * sproutframe->height ); - mod->radius = max( mod->radius, sproutframe->radius ); - } - - mod->type = mod_sprite; - mod->touchFrame = tr.registration_sequence; // register model -} - -#endif - //============================================================================= /* @@ -2122,7 +2063,7 @@ void R_BeginRegistration( const char *mapname, const dvis_t *visData ) if( com.strcmp( r_models[0].name, fullname )) { Mod_FreeModel( &r_models[0] ); - RI.surfmbuffers = NULL; + R_NewMap (); } else { diff --git a/render/r_model.h b/render/r_model.h index 366b74d5..8e7ce14e 100644 --- a/render/r_model.h +++ b/render/r_model.h @@ -243,73 +243,11 @@ typedef struct /* ============================================================================== -SKELETAL MODELS +STUDIO MODELS ============================================================================== */ -// -// in memory representation -// -#define SKM_MAX_WEIGHTS 4 - -// -// in memory representation -// -typedef struct -{ - ref_shader_t *shader; -} mskskin_t; - -typedef struct -{ - char name[SKM_MAX_NAME]; - - float *influences; - unsigned int *bones; - - unsigned int numverts; - vec4_t *xyzArray; - vec4_t *normalsArray; - vec2_t *stArray; - vec4_t *sVectorsArray; - - unsigned int numtris; - elem_t *elems; - - unsigned int numreferences; - unsigned int *references; - - mskskin_t skin; -} mskmesh_t; - -typedef struct -{ - char name[SKM_MAX_NAME]; - signed int parent; - unsigned int flags; -} mskbone_t; - -typedef struct -{ - vec3_t mins, maxs; - float radius; - bonepose_t *boneposes; -} mskframe_t; - -typedef struct -{ - unsigned int numbones; - mskbone_t *bones; - - unsigned int nummeshes; - mskmesh_t *meshes; - - unsigned int numframes; - mskframe_t *frames; - bonepose_t *invbaseposes; -} mskmodel_t; - /* ============================================================================== @@ -317,32 +255,27 @@ SPRITE MODELS ============================================================================== */ - -#ifdef QUAKE2_JUNK - // // in memory representation // typedef struct { - int width, height; - int origin_x, origin_y; // raster coordinates inside pic + int width, height; + int origin_x, origin_y; // raster coordinates inside pic - char name[SPRITE_MAX_NAME]; - ref_shader_t *shader; + char name[64]; + ref_shader_t *shader; - float mins[3], maxs[3]; - float radius; + float mins[3], maxs[3]; + float radius; } sframe_t; typedef struct { - int numframes; + int numframes; sframe_t *frames; } smodel_t; -#endif - //=================================================================== // @@ -379,18 +312,15 @@ void R_InitModels( void ); void R_ShutdownModels( void ); void Mod_ClearAll( void ); -ref_model_t *Mod_ForName( const char *name, bool crash ); +ref_model_t *Mod_ForName( const char *name, bool crash ); mleaf_t *Mod_PointInLeaf( float *p, ref_model_t *model ); byte *Mod_ClusterPVS( int cluster, ref_model_t *model ); +uint Mod_Handle( ref_model_t *mod ); +ref_model_t *Mod_ForHandle( unsigned int elem ); -unsigned int Mod_Handle( ref_model_t *mod ); -ref_model_t *Mod_ForHandle( unsigned int elem ); - -#define Mod_Malloc( mod, size ) Mem_Alloc( ( mod )->mempool, size ) +#define Mod_Malloc( mod, size ) Mem_Alloc(( mod )->mempool, size ) #define Mod_Free( data ) Mem_Free( data ) - void Mod_StripLODSuffix( char *name ); - void Mod_Modellist_f( void ); #endif /*__R_MODEL_H__*/ diff --git a/render/r_poly.c b/render/r_poly.c index 928c7517..bca5c7d7 100644 --- a/render/r_poly.c +++ b/render/r_poly.c @@ -502,11 +502,11 @@ int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], in VectorCopy( axis[i], fragmentPlanes[i*2].normal ); fragmentPlanes[i*2].dist = d - radius; - PlaneClassify( &fragmentPlanes[i*2] ); + fragmentPlanes[i*2].type = PlaneTypeForNormal( fragmentPlanes[i*2].normal ); VectorNegate( axis[i], fragmentPlanes[i*2+1].normal ); fragmentPlanes[i*2+1].dist = -d - radius; - PlaneClassify( &fragmentPlanes[i*2+1] ); + fragmentPlanes[i*2+1].type = PlaneTypeForNormal( fragmentPlanes[i*2+1].normal ); } R_RecursiveFragmentNode (); diff --git a/render/r_program.c b/render/r_program.c index 58bca97f..2fabe90c 100644 --- a/render/r_program.c +++ b/render/r_program.c @@ -22,14 +22,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_local.h" -#define APPLICATION "Xash3D" -#define MAX_GLSL_PROGRAMS 1024 +#define APPLICATION "Xash3D" +#define MAX_GLSL_PROGRAMS 1024 +#define R_GLSLProgramCopyString( str ) com.stralloc( r_glslProgramsPool, str, __FILE__, __LINE__ ) typedef struct { - int bit; - const char *define; - const char *suffix; + int bit; + const char *define; + const char *suffix; } glsl_feature_t; typedef struct @@ -77,9 +78,9 @@ R_InitGLSLPrograms */ void R_InitGLSLPrograms( void ) { - int features = 0; + int features = 0; - memset( r_glslprograms, 0, sizeof( r_glslprograms ) ); + Mem_Set( r_glslprograms, 0, sizeof( r_glslprograms )); if( !GL_Support( R_SHADER_GLSL100_EXT )) return; @@ -109,21 +110,6 @@ void R_InitGLSLPrograms( void ) R_RegisterGLSLProgram( DEFAULT_GLSL_OUTLINE_PROGRAM, r_defaultOutlineGLSLProgram, 0|features ); } -/* -================ -R_GLSLProgramCopyString -================ -*/ -static char *R_GLSLProgramCopyString( const char *in ) -{ - char *out; - - out = Mem_Alloc( r_glslProgramsPool, ( strlen( in ) + 1 ) ); - strcpy( out, in ); - - return out; -} - /* ================ R_DeleteGLSLProgram @@ -151,7 +137,7 @@ static void R_DeleteGLSLProgram( glsl_program_t *program ) if( program->name ) Mem_Free( program->name ); - memset( program, 0, sizeof( glsl_program_t ) ); + Mem_Set( program, 0, sizeof( glsl_program_t )); } /* @@ -1008,10 +994,10 @@ R_ProgramList_f */ void R_ProgramList_f( void ) { - int i; + int i; glsl_program_t *program; - string fullName; - const char **header; + string fullName; + const char **header; Msg( "------------------\n" ); for( i = 0, program = r_glslprograms; i < MAX_GLSL_PROGRAMS; i++, program++ ) @@ -1020,7 +1006,7 @@ void R_ProgramList_f( void ) break; com.strncpy( fullName, program->name, sizeof( fullName ) ); - header = R_ProgramFeatures2Defines( program->features, fullName, sizeof( fullName ) ); + header = R_ProgramFeatures2Defines( program->features, fullName, sizeof( fullName )); Msg( " %3i %s\n", i+1, fullName ); } @@ -1118,16 +1104,11 @@ R_GetProgramUniformLocations */ static void R_GetProgramUniformLocations( glsl_program_t *program ) { - int i; - int locBaseTexture, - locNormalmapTexture, - locGlossTexture, - locDecalTexture, - locLightmapTexture[LM_STYLES], - locDuDvMapTexture, - locReflectionTexture, - locRefractionTexture, - locShadowmapTexture; + int i; + int locBaseTexture, locNormalmapTexture, locGlossTexture; + int locDecalTexture, locLightmapTexture[LM_STYLES]; + int locDuDvMapTexture, locReflectionTexture; + int locRefractionTexture, locShadowmapTexture; char uniformName[128]; program->locEyeOrigin = pglGetUniformLocationARB( program->object, "EyeOrigin" ); @@ -1174,25 +1155,17 @@ static void R_GetProgramUniformLocations( glsl_program_t *program ) program->locProjDistance = pglGetUniformLocationARB( program->object, "ProjDistance" ); - if( locBaseTexture >= 0 ) - pglUniform1iARB( locBaseTexture, 0 ); - if( locDuDvMapTexture >= 0 ) - pglUniform1iARB( locDuDvMapTexture, 0 ); + if( locBaseTexture >= 0 ) pglUniform1iARB( locBaseTexture, 0 ); + if( locDuDvMapTexture >= 0 ) pglUniform1iARB( locDuDvMapTexture, 0 ); - if( locNormalmapTexture >= 0 ) - pglUniform1iARB( locNormalmapTexture, 1 ); - if( locGlossTexture >= 0 ) - pglUniform1iARB( locGlossTexture, 2 ); - if( locDecalTexture >= 0 ) - pglUniform1iARB( locDecalTexture, 3 ); + if( locNormalmapTexture >= 0 ) pglUniform1iARB( locNormalmapTexture, 1 ); + if( locGlossTexture >= 0 ) pglUniform1iARB( locGlossTexture, 2 ); + if( locDecalTexture >= 0 ) pglUniform1iARB( locDecalTexture, 3 ); - if( locReflectionTexture >= 0 ) - pglUniform1iARB( locReflectionTexture, 2 ); - if( locRefractionTexture >= 0 ) - pglUniform1iARB( locRefractionTexture, 3 ); + if( locReflectionTexture >= 0 ) pglUniform1iARB( locReflectionTexture, 2 ); + if( locRefractionTexture >= 0 ) pglUniform1iARB( locRefractionTexture, 3 ); - if( locShadowmapTexture >= 0 ) - pglUniform1iARB( locShadowmapTexture, 0 ); + if( locShadowmapTexture >= 0 ) pglUniform1iARB( locShadowmapTexture, 0 ); for( i = 0; i < LM_STYLES; i++ ) { @@ -1208,8 +1181,8 @@ R_ShutdownGLSLPrograms */ void R_ShutdownGLSLPrograms( void ) { - int i; - glsl_program_t *program; + int i; + glsl_program_t *program; if( !r_glslProgramsPool ) return; @@ -1225,4 +1198,4 @@ void R_ShutdownGLSLPrograms( void ) } Mem_FreePool( &r_glslProgramsPool ); -} +} \ No newline at end of file diff --git a/render/r_public.h b/render/r_public.h index 787bc314..3188d3c2 100644 --- a/render/r_public.h +++ b/render/r_public.h @@ -26,21 +26,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MAX_POLY_VERTS 3000 #define MAX_POLYS 2048 -// skm flags -#define SKM_ATTACHMENT_BONE 1 - typedef struct { vec3_t axis[3]; vec3_t origin; } orientation_t; -typedef struct -{ - quat_t quat; - vec3_t origin; -} bonepose_t; - typedef struct { float rgb[3]; // 0.0 - 2.0 @@ -132,13 +123,11 @@ typedef struct entity_s vec3_t movedir; // forward vector that computed on a server vec3_t origin, origin2; vec3_t lightingOrigin; - bonepose_t *boneposes; // pretransformed boneposes for current frame /* ** previous data for lerping */ int oldframe; - bonepose_t *oldboneposes; // pretransformed boneposes for old frame /* ** texturing @@ -171,35 +160,22 @@ typedef struct entity_s void R_ModelBounds( const struct ref_model_s *model, vec3_t mins, vec3_t maxs ); struct ref_model_s *R_RegisterModel( const char *name ); -struct ref_shader_s *R_RegisterPic( const char *name ); -struct ref_shader_s *R_RegisterShader( const char *name ); -struct ref_shader_s *R_RegisterSkin( const char *name ); struct skinfile_s *R_RegisterSkinFile( const char *name ); -void R_ClearScene( void ); -void R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, const struct ref_shader_s *shader ); -bool R_AddPolyToScene( const poly_t *poly ); -void R_AddLightStyleToScene( int style, float r, float g, float b ); -void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader ); -void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool redraw ); - -void R_SetCustomColor( int num, int r, int g, int b ); -void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ); - -bool R_LerpTag( orientation_t *orient, const struct ref_model_s *mod, int oldframe, int frame, float lerpfrac, - const char *name ); - -int R_SkeletalGetNumBones( const struct ref_model_s *mod, int *numFrames ); -int R_SkeletalGetBoneInfo( const struct ref_model_s *mod, int bone, char *name, size_t name_size, int *flags ); -void R_SkeletalGetBonePose( const struct ref_model_s *mod, int bone, int frame, bonepose_t *bonepose ); - -int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts, - int maxfragments, fragment_t *fragments ); - -void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out ); +void R_ClearScene( void ); +void R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, const struct ref_shader_s *shader ); +bool R_AddPolyToScene( const poly_t *poly ); +void R_AddLightStyleToScene( int style, float r, float g, float b ); +void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader ); +void R_DrawStretchRaw( int x, int y, int w, int h, int cols, int rows, const byte *data, bool redraw ); +void R_SetCustomColor( int num, int r, int g, int b ); +void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ); +bool R_LerpTag( orientation_t *orient, const struct ref_model_s *mod, int oldframe, int frame, float lerpfrac, const char *name ); +int R_GetClippedFragments( const vec3_t origin, float radius, vec3_t axis[3], int maxfverts, vec3_t *fverts, + int maxfragments, fragment_t *fragments ); +void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out ); const char *R_SpeedsMessage( char *out, size_t size ); -void GLimp_AppActivate( bool active ); // Xash renderer exports bool R_Init( bool full ); diff --git a/render/r_register.c b/render/r_register.c index cb190607..71243cef 100644 --- a/render/r_register.c +++ b/render/r_register.c @@ -41,6 +41,7 @@ cvar_t *r_ignorehwgamma; cvar_t *r_check_errors; cvar_t *r_overbrightbits; cvar_t *r_mapoverbrightbits; +cvar_t *r_vertexbuffers; cvar_t *r_flares; cvar_t *r_flaresize; cvar_t *r_flarefade; @@ -533,6 +534,7 @@ void GL_InitCommands( void ) r_ignorehwgamma = Cvar_Get( "r_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" ); r_overbrightbits = Cvar_Get( "r_overbrightbits", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "renderer overbright bits" ); r_mapoverbrightbits = Cvar_Get( "r_mapoverbrightbits", "2", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "current map overbright bits" ); + r_vertexbuffers = Cvar_Get( "r_vertexbuffers", "0", CVAR_ARCHIVE, "store vertex data in VBOs" ); r_detailtextures = Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE, "enable or disable detail textures" ); r_flares = Cvar_Get( "r_flares", "0", CVAR_ARCHIVE, "enable flares rendering" ); @@ -550,7 +552,7 @@ void GL_InitCommands( void ) r_fastsky = Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE, "enable algorhytem fo fast sky rendering (for old machines)" ); r_portalonly = Cvar_Get( "r_portalonly", "0", 0, "render only portals" ); r_portalmaps = Cvar_Get( "r_portalmaps", "1", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "use portal maps for portal rendering" ); - r_portalmaps_maxtexsize = Cvar_Get( "r_portalmaps_maxtexsize", "800", CVAR_ARCHIVE, "portal maps texture dims" ); + r_portalmaps_maxtexsize = Cvar_Get( "r_portalmaps_maxtexsize", "512", CVAR_ARCHIVE, "portal maps texture dims" ); r_allow_software = Cvar_Get( "r_allow_software", "0", 0, "allow OpenGL software emulation" ); r_3dlabs_broken = Cvar_Get( "r_3dlabs_broken", "1", CVAR_ARCHIVE, "3dLabs renderer issues" ); @@ -650,7 +652,7 @@ void GL_InitBackend( void ) if(FS_GetParmFromCmdLine( "-dev", dev_level )) glw_state.developer = com.atoi( dev_level ); - GL_SetDefaultState(); // FIXME stupid name for allocate arrays + GL_SetDefaultState(); } void GL_ShutdownBackend( void ) @@ -800,21 +802,7 @@ GL_SetDefaultState */ static void GL_SetDefaultState( void ) { - // FIXME: dynamically allocate these? - static GLuint r_currentTextures[MAX_TEXTURE_UNITS]; - static int r_currentEnvModes[MAX_TEXTURE_UNITS]; - static bool r_texIdentityMatrix[MAX_TEXTURE_UNITS]; - static int r_genSTEnabled[MAX_TEXTURE_UNITS]; - static int r_texCoordArrayMode[MAX_TEXTURE_UNITS]; - Mem_Set( &glState, 0, sizeof( glState )); - - glState.currentTextures = r_currentTextures; - glState.currentEnvModes = r_currentEnvModes; - glState.texIdentityMatrix = r_texIdentityMatrix; - glState.genSTEnabled = r_genSTEnabled; - glState.texCoordArrayMode = r_texCoordArrayMode; - GL_SetDefaultTexState (); glState.initializedMedia = false; @@ -1028,11 +1016,6 @@ void GL_InitExtensions( void ) Image_Init( NULL, flags ); glw_state.initialized = true; - - // gl_ext_vertex_buffer_object is crashy.. - // FIXME: QFusion render bug - Cvar_Set( "gl_vertex_buffer_object", "0" ); - GL_SetExtension( R_ARB_VERTEX_BUFFER_OBJECT_EXT, false ); } /* @@ -1136,4 +1119,26 @@ void R_Shutdown( bool full ) // shut down OS specific OpenGL stuff like contexts, etc. R_Free_OpenGL(); } +} + +/* +=============== +R_NewMap + +do some cleanup operations +=============== +*/ +void R_NewMap( void ) +{ + R_ShutdownOcclusionQueries(); + R_FreeMeshLists(); + + R_InitMeshLists(); + R_InitOcclusionQueries(); + + R_InitLightStyles(); // clear lightstyles + R_InitCustomColors(); // clear custom colors + + GL_SetDefaultTexState (); + Mem_Set( &RI, 0, sizeof( refinst_t )); } \ No newline at end of file diff --git a/render/r_shader.c b/render/r_shader.c index b33af99f..d0d62bab 100644 --- a/render/r_shader.c +++ b/render/r_shader.c @@ -1444,10 +1444,10 @@ static bool Shaderpass_NormalMap( ref_shader_t *shader, ref_stage_t *pass, scrip static bool Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script_t *script ) { - int flags; - float bumpScale = 0; - string name; - token_t tok; + int flags; + float bumpScale = 0; + const char *name; + token_t tok; if( !GL_Support( R_SHADER_GLSL100_EXT )) { @@ -1469,17 +1469,24 @@ static bool Shaderpass_Material( ref_shader_t *shader, ref_stage_t *pass, script pass->flags &= ~(SHADERSTAGE_ANIMFREQUENCY|SHADERSTAGE_FRAMES); } - com.strncpy( name, tok.string, sizeof( name )); flags = Shader_SetImageFlags( shader ); - while( 1 ) - { - if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )) - break; + if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )); + return false; - com.strncat( name, " ", sizeof( name )); - com.strncat( name, tok.string, sizeof( name )); + if( !com.stricmp( tok.string, "$rgb" )) + { + if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )); + return false; + name = va( "clearPixels( \"%s\", alpha );", tok.string ); } + else if( !com.stricmp( tok.string, "$alpha" )) + { + if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES2, &tok )); + return false; + name = va( "clearPixels( \"%s\", color );", tok.string ); + } + else name = tok.string; pass->textures[0] = Shader_FindImage( shader, name, flags ); if( pass->textures[0] == tr.defaultTexture ) @@ -2398,6 +2405,11 @@ void R_ShaderDump_f( void ) Msg( "^1%s%s\n", name, cache->buffer ); } +void R_RegisterBuiltinShaders( void ) +{ + tr.defaultShader = R_LoadShader( "*black", SHADER_NOMIP, true, (TF_NOMIPMAP|TF_NOPICMIP), SHADER_UNKNOWN ); +} + void R_InitShaders( void ) { script_t *script; @@ -2432,6 +2444,8 @@ void R_InitShaders( void ) r_spriteFrequency = 0.0f; r_numSpriteTextures = 0; r_spriteRenderMode = kRenderNormal; + + R_RegisterBuiltinShaders (); } void Shader_TouchImages( ref_shader_t *shader, bool free_unused ) @@ -3518,14 +3532,14 @@ ref_shader_t *R_LoadShader( const char *name, int type, bool forceDefault, int a shortname[length] = 0; // see if already loaded - hashKey = Com_HashKey( name, SHADERS_HASH_SIZE ); + hashKey = Com_HashKey( shortname, SHADERS_HASH_SIZE ); for( shader = r_shadersHash[hashKey]; shader; shader = shader->nextHash ) { if( shader->type != type || ( shader->type == ignoreType )) continue; - if( !com.stricmp( shader->name, name )) + if( !com.stricmp( shader->name, shortname )) { // prolonge registration Shader_TouchImages( shader, false ); @@ -3634,21 +3648,4 @@ void R_ShaderSetRenderMode( kRenderMode_t mode ) void R_ShaderAddSpriteIntervals( float interval ) { r_spriteFrequency += interval; -} - - -// FIXME: get rid of this -ref_shader_t *R_RegisterPic( const char *name ) -{ - return R_LoadShader( name, SHADER_NOMIP, false, 0, SHADER_INVALID ); -} - -ref_shader_t *R_RegisterShader( const char *name ) -{ - return R_LoadShader( name, SHADER_TEXTURE, false, 0, SHADER_INVALID ); -} - -ref_shader_t *R_RegisterSkin( const char *name ) -{ - return R_LoadShader( name, SHADER_ALIAS, false, 0, SHADER_INVALID ); -} +} \ No newline at end of file diff --git a/render/r_shadow.c b/render/r_shadow.c index 2888f87c..7d50857c 100644 --- a/render/r_shadow.c +++ b/render/r_shadow.c @@ -288,10 +288,18 @@ bool R_AddShadowCaster( ref_entity_t *ent ) r_numShadowGroups++; add: // get model bounds - if( ent->model->type == mod_alias ) + switch( ent->model->type ) + { + case mod_alias: R_AliasModelBBox( ent, mins, maxs ); - else - R_SkeletalModelBBox( ent, mins, maxs ); + break; + case mod_studio: + break; + default: + VectorClear( mins ); + VectorClear( maxs ); + break; + } for( i = 0; i < 3; i++ ) { diff --git a/render/r_skin.c b/render/r_skin.c index 64316813..3e8132f4 100644 --- a/render/r_skin.c +++ b/render/r_skin.c @@ -20,143 +20,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_local.h" +#define SkinFile_CopyString( str ) com.stralloc( r_skinsPool, str, __FILE__, __LINE__ ) + typedef struct { - char *meshname; - ref_shader_t *shader; + char *meshname; + ref_shader_t *shader; } mesh_shader_pair_t; typedef struct skinfile_s { - char *name; - + char *name; mesh_shader_pair_t *pairs; - int numpairs; + int numpairs; } skinfile_t; -static skinfile_t r_skinfiles[MAX_SKINFILES]; -static byte *r_skinsPool; - -// Com_ParseExt it's temporary stuff -#define MAX_TOKEN_CHARS 1024 -char com_token[MAX_TOKEN_CHARS]; - -/* -============== -COM_ParseExt - -Parse a token out of a string -============== -*/ -char *COM_ParseExt( const char **data_p, bool nl ) -{ - int c; - int len; - const char *data; - bool newlines = false; - - data = *data_p; - len = 0; - com_token[0] = 0; - - if (!data) - { - *data_p = NULL; - return ""; - } - -// skip whitespace -skipwhite: - while ( (c = *data) <= ' ') - { - if (c == 0) - { - *data_p = NULL; - return ""; - } - if (c == '\n') - newlines = true; - data++; - } - - if ( newlines && !nl ) - { - *data_p = data; - return com_token; - } - - // skip // comments - if (c == '/' && data[1] == '/') - { - data += 2; - - while (*data && *data != '\n') - data++; - goto skipwhite; - } - - // skip /* */ comments - if (c == '/' && data[1] == '*') - { - data += 2; - - while (1) - { - if (!*data) - break; - if (*data != '*' || *(data+1) != '/') - data++; - else - { - data += 2; - break; - } - } - goto skipwhite; - } - - // handle quoted strings specially - if (c == '\"') - { - data++; - while (1) - { - c = *data++; - if (c=='\"' || !c) - { - if (len == MAX_TOKEN_CHARS) - len = 0; - com_token[len] = 0; - *data_p = data; - return com_token; - } - if (len < MAX_TOKEN_CHARS) - { - com_token[len] = c; - len++; - } - } - } - -// parse a regular word - do - { - if (len < MAX_TOKEN_CHARS) - { - com_token[len] = c; - len++; - } - data++; - c = *data; - } while (c>32); - - if (len == MAX_TOKEN_CHARS) - len = 0; - com_token[len] = 0; - - *data_p = data; - return com_token; -} +static skinfile_t r_skinfiles[MAX_SKINFILES]; +static byte *r_skinsPool; /* ================ @@ -166,23 +46,7 @@ R_InitSkinFiles void R_InitSkinFiles( void ) { r_skinsPool = Mem_AllocPool( "Skins" ); - - memset( r_skinfiles, 0, sizeof( r_skinfiles ) ); -} - -/* -================ -SkinFile_CopyString -================ -*/ -static char *SkinFile_CopyString( const char *in ) -{ - char *out; - - out = Mem_Alloc( r_skinsPool, ( strlen( in ) + 1 ) ); - strcpy( out, in ); - - return out; + Mem_Set( r_skinfiles, 0, sizeof( r_skinfiles )); } /* @@ -192,15 +56,14 @@ SkinFile_FreeSkinFile */ static void SkinFile_FreeSkinFile( skinfile_t *skinfile ) { - int i; + int i; for( i = 0; i < skinfile->numpairs; i++ ) Mem_Free( skinfile->pairs[i].meshname ); Mem_Free( skinfile->pairs ); Mem_Free( skinfile->name ); - - memset( skinfile, 0, sizeof( skinfile_t ) ); + Mem_Set( skinfile, 0, sizeof( skinfile_t )); } /* @@ -232,33 +95,40 @@ SkinFile_ParseBuffer */ static int SkinFile_ParseBuffer( char *buffer, mesh_shader_pair_t *pairs ) { - int numpairs; - char *ptr, *t, *token; + int numpairs; + string skinname; + string meshname; + script_t *script; + token_t tok; - ptr = buffer; + script = Com_OpenScript( "skinfile", buffer, com.strlen( buffer )); numpairs = 0; - while( ptr ) + while( 1 ) { - token = COM_ParseExt( &ptr, false ); - if( !token[0] ) - continue; - - t = strchr( token, ',' ); - if( !t ) - continue; - if( *( t+1 ) == '\0' || *( t+1 ) == '\n' ) - continue; + if( !Com_ReadToken( script, SC_ALLOW_NEWLINES, &tok )) // skip tag + break; + if( !com.strcmp( tok.string, "," )) + { + if( !Com_ReadToken( script, SC_ALLOW_PATHNAMES, &tok )) + continue; // tag without shadername + com.strncpy( skinname, tok.string, sizeof( skinname )); + FS_StripExtension( skinname ); + } + else + { + com.strncpy( meshname, tok.string, sizeof( meshname )); + continue; // waiting for ',' + } if( pairs ) { - *t = 0; - pairs[numpairs].meshname = SkinFile_CopyString( token ); - pairs[numpairs].shader = R_RegisterSkin( token + strlen( token ) + 1 ); + pairs[numpairs].meshname = SkinFile_CopyString( meshname ); + pairs[numpairs].shader = R_LoadShader( skinname, SHADER_ALIAS, false, 0, SHADER_INVALID ); } - numpairs++; } + Com_CloseScript( script ); return numpairs; } diff --git a/render/r_skm.c b/render/r_skm.c index 103eb5bd..0cb023a1 100644 --- a/render/r_skm.c +++ b/render/r_skm.c @@ -284,7 +284,8 @@ void Mod_LoadSkeletalModel( ref_model_t *mod, ref_model_t *parent, const void *b com.strncpy( poutmesh->name, pinmesh->meshname, sizeof( poutmesh->name ) ); Mod_StripLODSuffix( poutmesh->name ); - poutmesh->skin.shader = R_RegisterSkin( pinmesh->shadername ); + FS_StripExtension( pinmesh->shadername ); + poutmesh->skin.shader = R_LoadShader( pinmesh->shadername, SHADER_ALIAS, false, 0, SHADER_INVALID ); R_DeformvBBoxForShader( poutmesh->skin.shader, ebbox ); pinreferences = ( elem_t *)( ( byte * )pinmodel + LittleLong( pinmesh->ofs_references ) ); diff --git a/render/r_sky.c b/render/r_sky.c index 863069fb..73629769 100644 --- a/render/r_sky.c +++ b/render/r_sky.c @@ -253,22 +253,12 @@ Draw dummy skybox side to prevent the HOM effect */ static void R_DrawBlackBottom( skydome_t *skydome ) { - int features; - ref_shader_t *shader; + int features; - // FIXME: register another shader instead maybe? - shader = R_OcclusionShader (); - - features = shader->features; + features = tr.defaultShader->features; if( r_shownormals->integer ) features |= MF_NORMALS; - - // HACKHACK skies ought not to write to depth buffer - shader->flags &= ~SHADER_DEPTHWRITE; - shader->stages[0].glState &= ~GLSTATE_DEPTHWRITE; - R_DrawSkySide( skydome, 5, shader, features ); - shader->stages[0].glState |= GLSTATE_DEPTHWRITE; - shader->flags |= SHADER_DEPTHWRITE; + R_DrawSkySide( skydome, 5, tr.defaultShader, features ); } /* @@ -370,8 +360,7 @@ void R_DrawSky( ref_shader_t *shader ) for( i = 0; i < 5; i++ ) { - if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || - RI.skyMins[1][i] >= RI.skyMaxs[1][i] ) + if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] ) continue; flush = true; @@ -382,9 +371,7 @@ void R_DrawSky( ref_shader_t *shader ) skydome->meshes[i].stArray = skydome->sphereStCoords[i]; R_PushMesh( &skydome->meshes[i], features ); } - - if( flush ) - R_RenderMeshBuffer( mbuffer ); + if( flush ) R_RenderMeshBuffer( mbuffer ); } if( skydome->nearboxShaders[0] ) diff --git a/render/r_surf.c b/render/r_surf.c index 2d98473f..7e7465e2 100644 --- a/render/r_surf.c +++ b/render/r_surf.c @@ -335,10 +335,10 @@ R_RecursiveWorldNode */ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigned int dlightbits ) { - unsigned int i, newDlightbits; - unsigned int bit; - const cplane_t *clipplane; - mleaf_t *pleaf; + uint i, newDlightbits; + const cplane_t *clipplane; + int clipped; + mleaf_t *pleaf; while( 1 ) { @@ -347,18 +347,16 @@ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigne if( clipflags ) { - for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, clipplane = RI.frustum; i > 0; i--, bit<<=1, clipplane++ ) + for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ ) { - if( clipflags & bit ) - { - int clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane ); - if( clipped == 2 ) - return; - if( clipped == 1 ) - clipflags &= ~bit; // node is entirely on screen - } + if(!(clipflags & (1<mins, node->maxs, clipplane ); + if( clipped == 2 ) return; + if( clipped == 1 ) clipflags &= ~(1<plane ) break; @@ -368,16 +366,16 @@ static void R_RecursiveWorldNode( mnode_t *node, unsigned int clipflags, unsigne { float dist; - for( i = 0, bit = 1; i < r_numDlights; i++, bit <<= 1 ) + for( i = 0; i < r_numDlights; i++ ) { - if( !( dlightbits & bit ) ) + if( !( dlightbits & (1<plane ); if( dist < -r_dlights[i].intensity ) - dlightbits &= ~bit; + dlightbits &= ~(1<numleafs, pleaf = r_worldbrushmodel->leafs; j > 0; j--, pleaf++ ) { @@ -455,16 +453,15 @@ static void R_LinearShadowLeafs( void ) continue; cpf = RI.clipFlags; - for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, clipplane = RI.frustum; i > 0; i--, bit<<=1, clipplane++ ) + + for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ ) { int clipped = BoxOnPlaneSide( pleaf->mins, pleaf->maxs, clipplane ); - if( clipped == 2 ) - break; - if( clipped == 1 ) - cpf &= ~bit; // leaf is entirely on screen + if( clipped == 2 ) break; + if( clipped == 1 ) cpf &= ~(1<firstVisSurface, cpf ); c_world_leafs++; } diff --git a/render/render.dsp b/render/render.dsp index f2025775..90ccb029 100644 --- a/render/render.dsp +++ b/render/render.dsp @@ -194,10 +194,6 @@ SOURCE=.\r_skin.c # End Source File # Begin Source File -SOURCE=.\r_skm.c -# End Source File -# Begin Source File - SOURCE=.\r_sky.c # End Source File # Begin Source File diff --git a/render/render.plg b/render/render.plg index c5158a88..66e34829 100644 --- a/render/render.plg +++ b/render/render.plg @@ -6,6 +6,51 @@ --------------------Configuration: render - Win32 Debug--------------------

Command Lines

+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp" with contents +[ +/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\render\!debug/" /Fo"..\temp\render\!debug/" /Fd"..\temp\render\!debug/" /FD /c +"D:\Xash3D\src_main\render\r_image.c" +] +Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD5.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp" with contents +[ +msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\render\!debug/render.pdb" /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\temp\render\!debug/render.dll" /implib:"..\temp\render\!debug/render.lib" /pdbtype:sept +"\Xash3D\src_main\temp\render\!debug\cin.obj" +"\Xash3D\src_main\temp\render\!debug\r_alias.obj" +"\Xash3D\src_main\temp\render\!debug\r_backend.obj" +"\Xash3D\src_main\temp\render\!debug\r_bloom.obj" +"\Xash3D\src_main\temp\render\!debug\r_cin.obj" +"\Xash3D\src_main\temp\render\!debug\r_cull.obj" +"\Xash3D\src_main\temp\render\!debug\r_draw.obj" +"\Xash3D\src_main\temp\render\!debug\r_image.obj" +"\Xash3D\src_main\temp\render\!debug\r_light.obj" +"\Xash3D\src_main\temp\render\!debug\r_main.obj" +"\Xash3D\src_main\temp\render\!debug\r_math.obj" +"\Xash3D\src_main\temp\render\!debug\r_mesh.obj" +"\Xash3D\src_main\temp\render\!debug\r_model.obj" +"\Xash3D\src_main\temp\render\!debug\r_opengl.obj" +"\Xash3D\src_main\temp\render\!debug\r_poly.obj" +"\Xash3D\src_main\temp\render\!debug\r_program.obj" +"\Xash3D\src_main\temp\render\!debug\r_register.obj" +"\Xash3D\src_main\temp\render\!debug\r_shader.obj" +"\Xash3D\src_main\temp\render\!debug\r_shadow.obj" +"\Xash3D\src_main\temp\render\!debug\r_skin.obj" +"\Xash3D\src_main\temp\render\!debug\r_sky.obj" +"\Xash3D\src_main\temp\render\!debug\r_surf.obj" +] +Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD6.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat" with contents +[ +@echo off +copy \Xash3D\src_main\temp\render\!debug\render.dll "D:\Xash3D\bin\render.dll" +] +Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPD7.bat" +Compiling... +r_image.c +Linking... +

Output Window

+Performing Custom Build Step on \Xash3D\src_main\temp\render\!debug\render.dll +‘Є®ЇЁа®ў ­® д ©«®ў: 1. diff --git a/server/global/client.cpp b/server/global/client.cpp index 28bf8b45..7783c75c 100644 --- a/server/global/client.cpp +++ b/server/global/client.cpp @@ -1134,12 +1134,13 @@ const char *GetGameDescription( void ) { char token[256]; char szbuffer[128]; - char *pfile = (char *)LOAD_FILE( "gameinfo.txt", NULL ); + char *afile, *pfile = (char *)LOAD_FILE( "gameinfo.txt", NULL ); memset( text, 0, sizeof( text )); if( pfile ) { + afile = pfile; while( pfile ) { if( !stricmp( token, "title" )) @@ -1155,7 +1156,7 @@ const char *GetGameDescription( void ) } pfile = COM_ParseFile( pfile, token ); } - COM_FreeFile( pfile ); + COM_FreeFile( afile ); return text; } return "Half-Life"; diff --git a/server/global/utils.cpp b/server/global/utils.cpp index db297537..2aa3be28 100644 --- a/server/global/utils.cpp +++ b/server/global/utils.cpp @@ -1397,6 +1397,7 @@ void UTIL_PrecacheResourse( void ) char *pfile = (char *)LOAD_FILE( "scripts/precache.txt", NULL ); if( pfile ) { + char *afile = pfile; while( pfile ) { if( !stricmp( token, "entity" )) @@ -1436,7 +1437,7 @@ void UTIL_PrecacheResourse( void ) } pfile = COM_ParseFile( pfile, token ); } - COM_FreeFile( pfile ); + COM_FreeFile( afile ); } } diff --git a/server/monsters/player.cpp b/server/monsters/player.cpp index 80c47425..af8f7727 100644 --- a/server/monsters/player.cpp +++ b/server/monsters/player.cpp @@ -3859,23 +3859,24 @@ void CBasePlayer::CheatImpulseCommands( int iImpulse ) { gEvilImpulse101 = TRUE; char *pfile = (char *)LOAD_FILE( "scripts/impulse101.txt", NULL ); - int ItemName [256]; + int ItemName[256]; int count = 0; char token[32]; - if(pfile) + if( pfile ) { - while ( pfile ) + char *afile = pfile; + while( pfile ) { - //parsing impulse101.txt - pfile = COM_ParseFile(pfile, token); - if(strlen(token)) + // parsing impulse101.txt + pfile = COM_ParseFile( pfile, token ); + if(strlen( token )) { - ItemName[ count ] = ALLOC_STRING( (char *)token ); + ItemName[count] = ALLOC_STRING( (char *)token ); count++; } } - COM_FreeFile( pfile ); + COM_FreeFile( afile ); for( int i = 0; i < count; i++ ) GiveNamedItem( (char *)STRING( ItemName[i]) ); } diff --git a/server/server.plg b/server/server.plg new file mode 100644 index 00000000..2aaf2920 --- /dev/null +++ b/server/server.plg @@ -0,0 +1,100 @@ + + +
+

Build Log

+

+--------------------Configuration: server - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp" with contents +[ +/nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "./" /I "ents" /I "game" /I "global" /I "monsters" /I "../common" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"..\temp\server\!debug/" /Fo"..\temp\server\!debug/" /Fd"..\temp\server\!debug/" /FD /c +"D:\Xash3D\src_main\server\global\client.cpp" +] +Creating command line "cl.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBB.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp" with contents +[ +msvcrtd.lib /nologo /subsystem:windows /dll /incremental:yes /pdb:"..\temp\server\!debug/server.pdb" /debug /machine:I386 /nodefaultlib:"libc.lib" /def:".\server.def" /out:"..\temp\server\!debug/server.dll" /implib:"..\temp\server\!debug/server.lib" /pdbtype:sept +"\Xash3D\src_main\temp\server\!debug\ai_sound.obj" +"\Xash3D\src_main\temp\server\!debug\animating.obj" +"\Xash3D\src_main\temp\server\!debug\animation.obj" +"\Xash3D\src_main\temp\server\!debug\apache.obj" +"\Xash3D\src_main\temp\server\!debug\barnacle.obj" +"\Xash3D\src_main\temp\server\!debug\barney.obj" +"\Xash3D\src_main\temp\server\!debug\basebrush.obj" +"\Xash3D\src_main\temp\server\!debug\baseentity.obj" +"\Xash3D\src_main\temp\server\!debug\basefunc.obj" +"\Xash3D\src_main\temp\server\!debug\basefx.obj" +"\Xash3D\src_main\temp\server\!debug\baseinfo.obj" +"\Xash3D\src_main\temp\server\!debug\baseitem.obj" +"\Xash3D\src_main\temp\server\!debug\baselogic.obj" +"\Xash3D\src_main\temp\server\!debug\basemonster.obj" +"\Xash3D\src_main\temp\server\!debug\basemover.obj" +"\Xash3D\src_main\temp\server\!debug\baseother.obj" +"\Xash3D\src_main\temp\server\!debug\basepath.obj" +"\Xash3D\src_main\temp\server\!debug\basephys.obj" +"\Xash3D\src_main\temp\server\!debug\baserockets.obj" +"\Xash3D\src_main\temp\server\!debug\basetank.obj" +"\Xash3D\src_main\temp\server\!debug\basetrigger.obj" +"\Xash3D\src_main\temp\server\!debug\baseutil.obj" +"\Xash3D\src_main\temp\server\!debug\baseweapon.obj" +"\Xash3D\src_main\temp\server\!debug\baseworld.obj" +"\Xash3D\src_main\temp\server\!debug\client.obj" +"\Xash3D\src_main\temp\server\!debug\combat.obj" +"\Xash3D\src_main\temp\server\!debug\decals.obj" +"\Xash3D\src_main\temp\server\!debug\defaultai.obj" +"\Xash3D\src_main\temp\server\!debug\dll_int.obj" +"\Xash3D\src_main\temp\server\!debug\flyingmonster.obj" +"\Xash3D\src_main\temp\server\!debug\game.obj" +"\Xash3D\src_main\temp\server\!debug\gamerules.obj" +"\Xash3D\src_main\temp\server\!debug\generic.obj" +"\Xash3D\src_main\temp\server\!debug\globals.obj" +"\Xash3D\src_main\temp\server\!debug\gman.obj" +"\Xash3D\src_main\temp\server\!debug\hassassin.obj" +"\Xash3D\src_main\temp\server\!debug\headcrab.obj" +"\Xash3D\src_main\temp\server\!debug\hgrunt.obj" +"\Xash3D\src_main\temp\server\!debug\leech.obj" +"\Xash3D\src_main\temp\server\!debug\legacy.obj" +"\Xash3D\src_main\temp\server\!debug\lights.obj" +"\Xash3D\src_main\temp\server\!debug\multiplay_gamerules.obj" +"\Xash3D\src_main\temp\server\!debug\nodes.obj" +"\Xash3D\src_main\temp\server\!debug\osprey.obj" +"\Xash3D\src_main\temp\server\!debug\parent.obj" +"\Xash3D\src_main\temp\server\!debug\player.obj" +"\Xash3D\src_main\temp\server\!debug\rat.obj" +"\Xash3D\src_main\temp\server\!debug\roach.obj" +"\Xash3D\src_main\temp\server\!debug\saverestore.obj" +"\Xash3D\src_main\temp\server\!debug\scientist.obj" +"\Xash3D\src_main\temp\server\!debug\scripted.obj" +"\Xash3D\src_main\temp\server\!debug\sfx.obj" +"\Xash3D\src_main\temp\server\!debug\singleplay_gamerules.obj" +"\Xash3D\src_main\temp\server\!debug\sound.obj" +"\Xash3D\src_main\temp\server\!debug\squadmonster.obj" +"\Xash3D\src_main\temp\server\!debug\talkmonster.obj" +"\Xash3D\src_main\temp\server\!debug\teamplay_gamerules.obj" +"\Xash3D\src_main\temp\server\!debug\turret.obj" +"\Xash3D\src_main\temp\server\!debug\utils.obj" +"\Xash3D\src_main\temp\server\!debug\weapon_generic.obj" +"\Xash3D\src_main\temp\server\!debug\zombie.obj" +] +Creating command line "link.exe @C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBC.tmp" +Creating temporary file "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat" with contents +[ +@echo off +copy \Xash3D\src_main\temp\server\!debug\server.dll "D:\Xash3D\bin\server.dll" +] +Creating command line "C:\DOCUME~1\MIKE~1.MIK\LOCALS~1\Temp\RSPBD.bat" +Compiling... +client.cpp +Linking... +

Output Window

+Performing Custom Build Step on \Xash3D\src_main\temp\server\!debug\server.dll +‘Є®ЇЁа®ў ­® д ©«®ў: 1. + + + +

Results

+server.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/todo.log b/todo.log index 27d642bc..0a122e8d 100644 --- a/todo.log +++ b/todo.log @@ -11,9 +11,6 @@ fopen возвращал. fopen завешивает приложение, даже если перепутать местами + и a, при установке режима! -Memory Leaks: -Filesystem Pool растет на 4 килобайта после смены карты - Отложенные задачи: 1. Поддержка loop для ogg vorbis 2. переписать studiomdl для использования VFS @@ -98,7 +95,7 @@ Beta 13.12.08 64. ImageLoading from old render OK 65. envshot, skyshot swap angles to right pos 66. ShaderSystem from old render OK -67. fixup NPOT textures loading (screen textures) +67. fixup NPOT textures loading (screen textures) OK 68. add new shader types OK 69. implement oldareabits OK 70. repair fog texture OK @@ -107,9 +104,16 @@ Beta 13.12.08 73. shaders pasring OK 74. fixup 3D textures loading OK 75. ignore shader errors - just throw warnings OK -76. launch.dll ->release gl_invalid_enum +76. launch.dll ->release gl_invalid_enum OK 77. debug shader_free_unused mechanism OK -78. fix changemap errors -79. memory trash in render.dll - - +78. fix changemap errors OK +79. memory trash in render.dll OK +80. implement $rgb, $alpha OK +89. get rid of R_Upload32 OK +90. get rid of Com_ParseExt OK +91. Xash backend extensions +92. implement VBO OK +93. implement sky rotate +94. make default sky shader, R_SetupSky +95. support for custom tables (external) +96. implement sprite format diff --git a/vsound/s_load.c b/vsound/s_load.c index 8e5073d8..75276201 100644 --- a/vsound/s_load.c +++ b/vsound/s_load.c @@ -261,6 +261,7 @@ static bool S_LoadWAV( const char *name, byte **wav, wavinfo_t *info ) if( samples < info->samples ) { MsgDev( D_ERROR, "S_LoadWAV: %s has a bad loop length\n", name ); + Mem_Free( buffer ); return false; } }