28 Dec 2010

This commit is contained in:
g-cont 2010-12-28 00:00:00 +03:00 committed by Alibek Omarov
parent 7143afc284
commit 3b659054d8
98 changed files with 2207 additions and 35693 deletions

View File

@ -31,7 +31,6 @@ pm_shared\
public\
launch\
mainui\
vid_gl\
utils\
utils\vgui\
utils\vgui\include\

View File

@ -1,3 +1,11 @@
build ????
Render: fix decals serialization bug
Engine: fix movie plaback bug (black screen)
Engine: fix crash on loading encrypted client.dll
GameUI: now recalc resolution when vid_mode is changed
Sound: fix musicvolume bug
build 1418
Tools: move all tools into launch.dll

View File

@ -32,7 +32,7 @@ BRUSH MODELS
#define SURF_DRAWTILED BIT( 5 ) // face without lighmap
#define SURF_CONVEYOR BIT( 6 ) // scrolled texture
#define SURF_UNDERWATER BIT( 7 ) // caustics
#define SURF_DONTWARP BIT( 8 )
#define SURF_TRANSPARENT BIT( 8 ) // it's a transparent texture
// lightstyle management
#define LM_STYLES 4 // MAXLIGHTMAPS

View File

@ -1451,9 +1451,7 @@ pfnSPR_Draw
*/
static void pfnSPR_Draw( int frame, int x, int y, const wrect_t *prc )
{
GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA );
GL_TexEnv( GL_MODULATE );
GL_SetRenderMode( kRenderNormal );
SPR_DrawGeneric( frame, x, y, -1, -1, prc );
}

View File

@ -831,6 +831,8 @@ void CL_Crashed_f( void )
Host_WriteOpenGLConfig();
Host_WriteConfig(); // write config
// never write video.cfg here because reason to crash may be provoked
// with some renderer variables
VID_RestoreGamma();
}
@ -1620,6 +1622,7 @@ void CL_Shutdown( void )
if( !cls.initialized ) return;
Host_WriteOpenGLConfig ();
Host_WriteVideoConfig ();
Host_WriteConfig ();
IN_Shutdown ();

View File

@ -162,6 +162,8 @@ static void UI_DrawLogo( const char *filename, float x, float y, float width, fl
redraw = true;
}
GL_SetState( 0 );
GL_TexEnv( GL_REPLACE );
R_DrawStretchRaw( x, y, width, height, menu.logo_xres, menu.logo_yres, cin_data, redraw );
}

View File

@ -383,6 +383,7 @@ void SCR_VidInit( void )
menu.globals->scrWidth = scr_width->integer;
menu.globals->scrHeight = scr_height->integer;
SCR_RebuildGammaTable();
VGui_Startup ();
clgame.load_sequence++; // now all hud sprites are invalid

View File

@ -5,6 +5,7 @@
#include "common.h"
#include "client.h"
#include "gl_local.h"
#include <vfw.h> // video for windows
/*
@ -15,7 +16,6 @@ AVI PLAYING
=================================================================
*/
convar_t *vid_gamma;
static long xres, yres;
static float video_duration;
static float cin_time;
@ -133,13 +133,22 @@ SCR_RunCinematic
*/
void SCR_RunCinematic( void )
{
if( cls.state != ca_cinematic )
return;
if( !AVI_IsActive( cin_state ))
return;
if( vid_gamma->modified )
if( UI_IsVisible( ))
{
SCR_RebuildGammaTable();
vid_gamma->modified = false;
// these can happens when user set +menu_ option to cmdline
AVI_CloseVideo( cin_state );
cls.state = ca_disconnected;
Key_SetKeyDest( key_menu );
S_StopStreaming();
cls.movienum = -1;
cin_time = 0.0f;
return;
}
// advances cinematic time (ignores maxfps and host_framerate settings)
@ -170,7 +179,7 @@ qboolean SCR_DrawCinematic( void )
qboolean redraw = false;
byte *frame = NULL;
if( cin_time <= 0.0f )
if( !glw_state.initialized || cin_time <= 0.0f )
return false;
if( cin_frame != last_frame )
@ -275,9 +284,6 @@ SCR_InitCinematic
void SCR_InitCinematic( void )
{
AVIFileInit();
// used for movie gamma correction
vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" );
cin_state = AVI_GetState( CIN_MAIN );
SCR_RebuildGammaTable();

View File

@ -87,26 +87,6 @@ void V_SetupRefDef( void )
}
}
/*
===============
V_ApplyRefDef
apply pre-calculated values
===============
*/
void V_AddViewModel( void )
{
// add viewmodel only at firstperson pass when game not paused
if( cl.refdef.nextView || cl.refdef.paused || cl.thirdperson || cl.refdef.health <= 0 )
return;
// make sure what frame is valid and viewmodel is set
if( !cl.frame.valid || !clgame.viewent.model || cl.refdef.viewentity != ( cl.playernum + 1 ))
return;
CL_AddVisibleEntity( &clgame.viewent, ET_NORMAL );
}
/*
===============
V_CalcRefDef
@ -119,7 +99,6 @@ void V_CalcRefDef( void )
do
{
clgame.dllFuncs.pfnCalcRefdef( &cl.refdef );
V_AddViewModel();
R_RenderFrame( &cl.refdef, true );
cl.refdef.onlyClientDraw = false;
} while( cl.refdef.nextView );
@ -206,8 +185,8 @@ void V_PostRender( void )
CL_DrawDemoRecording();
R_ShowTextures();
CL_DrawHUD( CL_CHANGELEVEL );
UI_UpdateMenu( host.realtime );
Con_DrawConsole();
UI_UpdateMenu( host.realtime );
S_ExtraUpdate();
}

View File

@ -593,6 +593,7 @@ void CL_Download_f( void );
//
void SCR_VidInit( void );
void SCR_EndLoadingPlaque( void );
void SCR_RebuildGammaTable( void );
void SCR_RegisterShaders( void );
void SCR_MakeScreenShot( void );
void SCR_MakeLevelShot( void );

View File

@ -425,6 +425,10 @@ void GL_SetRenderMode( int mode )
{
int state, texEnv;
// GoldSrc in 2D mode uses default mode as TransTexture
if( glState.in2DMode && mode == kRenderNormal )
mode = kRenderTransTexture;
switch( mode )
{
case kRenderNormal:
@ -434,7 +438,7 @@ void GL_SetRenderMode( int mode )
break;
case kRenderTransColor:
state = GLSTATE_SRCBLEND_ZERO|GLSTATE_DSTBLEND_SRC_COLOR|GLSTATE_DEPTHWRITE;
texEnv = GL_DECAL;
texEnv = GL_REPLACE;
break;
case kRenderTransAlpha:
state = GLSTATE_AFUNC_GE128|GLSTATE_DEPTHWRITE;

View File

@ -658,7 +658,7 @@ static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *dec
for( i = 0; i < node->numsurfaces; i++, surf++ )
{
// never apply decals on the water or sky surfaces
if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY))
if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_TRANSPARENT|SURF_CONVEYOR))
continue;
R_DecalSurface( surf, decalinfo );
@ -862,7 +862,7 @@ void DrawSurfaceDecals( msurface_t *fa )
oldState = glState.flags;
oldTexEnv = glState.currentEnvModes[glState.activeTMU];
GL_SetState( GLSTATE_SRCBLEND_SRC_ALPHA|GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA|GLSTATE_OFFSET_FILL );
GL_TexEnv( GL_REPLACE );
GL_TexEnv( GL_MODULATE ); // receive renderamt from bmodels
for( p = fa->pdecals; p; p = p->pnext )
DrawSingleDecal( p, fa );

View File

@ -88,8 +88,8 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c
int width = 1, height = 1;
// check the dimensions
while( width < cols ) width <<= 1;
while( height < rows ) height <<= 1;
width = NearestPOW( cols, true );
height = NearestPOW( rows, false );
if( cols != width || rows != height )
{
@ -109,7 +109,7 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c
Host_Error( "R_DrawStretchRaw: size %i exceeds hardware limits\n", rows );
tex = R_GetTexture( tr.cinTexture );
GL_Bind( 0, tr.cinTexture );
GL_Bind( GL_TEXTURE0, tr.cinTexture );
if( cols == tex->width && rows == tex->height )
{

View File

@ -1159,10 +1159,10 @@ R_InitCinematicTexture
*/
static rgbdata_t *R_InitCinematicTexture( texFlags_t *flags )
{
r_image.width = r_image.height = 256;
r_image.buffer = data2D;
r_image.type = PF_RGBA_32;
r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA;
r_image.flags = IMAGE_HAS_COLOR;
r_image.width = r_image.height = 256;
r_image.size = r_image.width * r_image.height * 4;
*flags = TF_NOMIPMAP|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP;

View File

@ -520,8 +520,6 @@ extern glwstate_t glw_state;
extern convar_t *gl_allow_software;
extern convar_t *gl_texture_anisotropy;
extern convar_t *gl_extensions;
extern convar_t *gl_colorbits;
extern convar_t *gl_depthbits;
extern convar_t *gl_stencilbits;
extern convar_t *gl_texturebits;
extern convar_t *gl_ignorehwgamma;

View File

@ -368,11 +368,6 @@ static void R_Clear( int bitMask )
if( bits & GL_STENCIL_BUFFER_BIT )
pglClearStencil( 128 );
if( bits & GL_COLOR_BUFFER_BIT )
{
pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
}
pglClear( bits );
gldepthmin = 0.0f;
@ -742,6 +737,9 @@ void R_DrawEntitiesOnList( void )
CL_DrawParticles();
clgame.dllFuncs.pfnDrawTransparentTriangles ();
// FIXME: allow to brush and sprite viewmodel ?
R_DrawViewModel();
}
/*
@ -784,9 +782,8 @@ R_BeginFrame
*/
void R_BeginFrame( qboolean clearScene )
{
if( gl_clear->integer && clearScene )
if( gl_clear->integer && clearScene && cls.state != ca_cinematic )
{
pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
pglClear( GL_COLOR_BUFFER_BIT );
}

View File

@ -173,7 +173,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer )
pal = FS_LoadImage( "#normal.pal", src, 768 );
break;
case SPR_INDEXALPHA:
pal = FS_LoadImage( "#decal.pal", src, 768 );
pal = FS_LoadImage( "#indexalpha.pal", src, 768 );
break;
case SPR_ALPHTEST:
pal = FS_LoadImage( "#transparent.pal", src, 768 );
@ -938,9 +938,6 @@ void R_DrawSpriteModel( cl_entity_t *e )
break;
}
if( e->curstate.rendermode == kRenderGlow )
pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin ));
if( psprite->facecull == SPR_CULL_NONE )
GL_Cull( GL_NONE );
@ -969,9 +966,6 @@ void R_DrawSpriteModel( cl_entity_t *e )
}
}
if( e->curstate.rendermode == kRenderGlow )
pglDepthRange( gldepthmin, gldepthmax );
if( psprite->facecull == SPR_CULL_NONE )
GL_Cull( GL_FRONT );

View File

@ -43,6 +43,7 @@ typedef struct studiolight_s
convar_t *r_studio_lerping;
convar_t *r_studio_lambert;
convar_t *r_drawviewmodel;
convar_t *cl_himodels;
char model_name[64];
static r_studio_interface_t *pStudioDraw;
@ -90,6 +91,7 @@ void R_StudioInit( void )
r_studio_lambert = Cvar_Get( "r_studio_lambert", "2", CVAR_ARCHIVE, "bonelighting lambert value" );
r_studio_lerping = Cvar_Get( "r_studio_lerping", "1", CVAR_ARCHIVE, "enables studio animation lerping" );
r_drawviewmodel = Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" );
cl_himodels = Cvar_Get( "cl_himodels", "1", CVAR_ARCHIVE, "draw high-resolution player models in multiplayer" );
// recalc software X and Y alias scale (this stuff is used only by HL software renderer but who knews...)
@ -1994,6 +1996,7 @@ static void R_StudioSetupRenderer( int rendermode )
}
g_iRenderMode = bound( 0, rendermode, kRenderTransInverse + 1 );
pglShadeModel( GL_SMOOTH ); // enable gouraud shading
}
/*
@ -2016,6 +2019,7 @@ static void R_StudioRestoreRenderer( void )
GL_SetRenderMode( kRenderNormal );
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
pglScalef( 1.0f, 1.0f, 1.0f );
pglShadeModel( GL_FLAT );
}
/*
@ -2567,6 +2571,30 @@ void R_RunViewmodelEvents( void )
RI.currentmodel = NULL;
}
/*
=================
R_DrawViewModel
=================
*/
void R_DrawViewModel( void )
{
if( RI.refdef.onlyClientDraw || r_drawviewmodel->integer == 0 )
return;
// ignore in thirdperson, camera view or client is died
if( cl.thirdperson || cl.refdef.health <= 0 || cl.refdef.viewentity != ( cl.playernum + 1 ))
return;
RI.currententity = &clgame.viewent;
RI.currentmodel = RI.currententity->model;
if( !RI.currentmodel ) return;
pStudioDraw->StudioDrawModel( STUDIO_RENDER );
RI.currententity = NULL;
RI.currentmodel = NULL;
}
/*
====================
R_StudioLoadTexture

View File

@ -9,18 +9,16 @@
#include "cm_local.h"
#include "input.h"
#define MAX_PFDS 256
#define VID_DEFAULTMODE "1"
#define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1)
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE)
#define WINDOW_EX_STYLE (0)
#define GL_DRIVER_OPENGL "OpenGL32"
convar_t *renderinfo;
convar_t *gl_allow_software;
convar_t *gl_extensions;
convar_t *gl_colorbits;
convar_t *gl_alphabits;
convar_t *gl_depthbits;
convar_t *gl_stencilbits;
convar_t *gl_texturebits;
convar_t *gl_ignorehwgamma;
@ -39,6 +37,8 @@ convar_t *gl_finish;
convar_t *gl_clear;
convar_t *gl_test;
convar_t *r_xpos;
convar_t *r_ypos;
convar_t *r_width;
convar_t *r_height;
convar_t *r_speeds;
@ -490,23 +490,18 @@ void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cv
MsgDev( D_NOTE, "GL_CheckExtension: %s ", name );
if( gl_extensions->integer == 0 && r_ext != GL_OPENGL_110 )
{
MsgDev( D_NOTE, "- disabled\n" );
GL_SetExtension( r_ext, 0 ); // update render info
return;
}
if( cvarname )
{
// system config disable extensions
parm = Cvar_Get( cvarname, "1", CVAR_RENDERINFO, va( "enable or disable %s", name ));
GL_SetExtension( r_ext, parm->integer ); // update render info
if( parm->integer == 0 )
parm = Cvar_Get( cvarname, "1", CVAR_GLCONFIG, va( "enable or disable %s", name ));
if( parm->integer == 0 || ( gl_extensions->integer == 0 && r_ext != GL_OPENGL_110 ))
{
MsgDev( D_NOTE, "- disabled\n" );
GL_SetExtension( r_ext, 0 );
return; // nothing to process at
}
GL_SetExtension( r_ext, 1 );
}
if(( name[2] == '_' || name[3] == '_' ) && !com.strstr( glConfig.extensions_string, name ))
@ -676,139 +671,57 @@ qboolean GL_DeleteContext( void )
VID_ChoosePFD
=================
*/
static int VID_ChoosePFD( int colorBits, int alphaBits, int depthBits, int stencilBits )
static int VID_ChoosePFD( PIXELFORMATDESCRIPTOR *pfd, int colorBits, int alphaBits, int depthBits, int stencilBits )
{
PIXELFORMATDESCRIPTOR PFDs[MAX_PFDS], *current, *selected;
uint flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
int i, numPFDs, pixelFormat = 0;
int pixelFormat = 0;
MsgDev( D_NOTE, "VID_ChoosePFD( color %i, alpha %i, depth %i, stencil %i )\n", colorBits, alphaBits, depthBits, stencilBits );
// Fill out the PFD
pfd->nSize = sizeof (PIXELFORMATDESCRIPTOR);
pfd->nVersion = 1;
pfd->dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
pfd->iPixelType = PFD_TYPE_RGBA;
pfd->cColorBits = colorBits;
pfd->cRedBits = 0;
pfd->cRedShift = 0;
pfd->cGreenBits = 0;
pfd->cGreenShift = 0;
pfd->cBlueBits = 0;
pfd->cBlueShift = 0; // wow! Blue Shift %)
pfd->cAlphaBits = alphaBits;
pfd->cAlphaShift = 0;
pfd->cAccumBits = 0;
pfd->cAccumRedBits = 0;
pfd->cAccumGreenBits = 0;
pfd->cAccumBlueBits = 0;
pfd->cAccumAlphaBits= 0;
pfd->cDepthBits = depthBits;
pfd->cStencilBits = stencilBits;
pfd->cAuxBuffers = 0;
pfd->iLayerType = PFD_MAIN_PLANE;
pfd->bReserved = 0;
pfd->dwLayerMask = 0;
pfd->dwVisibleMask = 0;
pfd->dwDamageMask = 0;
// Count PFDs
if( glw_state.minidriver )
numPFDs = pwglDescribePixelFormat( glw_state.hDC, 0, 0, NULL );
else numPFDs = DescribePixelFormat( glw_state.hDC, 0, 0, NULL );
if( numPFDs > MAX_PFDS )
{
MsgDev( D_NOTE, "too many PFDs returned (%i > %i), reduce it\n", numPFDs, MAX_PFDS );
numPFDs = MAX_PFDS;
}
else if( numPFDs < 1 )
{
MsgDev( D_ERROR, "VID_ChoosePFD failed\n" );
return 0;
}
// run through all the PFDs, looking for the best match
for( i = 1, current = PFDs; i <= numPFDs; i++, current++ )
{
if( glw_state.minidriver )
pwglDescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current );
else DescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current );
// check acceleration
if(( current->dwFlags & PFD_GENERIC_FORMAT ) && !gl_allow_software->integer )
continue;
// check flags
if(( current->dwFlags & flags ) != flags )
continue;
// check pixel type
if( current->iPixelType != PFD_TYPE_RGBA )
continue;
// check color bits
if( current->cColorBits < colorBits )
continue;
// check alpha bits
if( current->cAlphaBits < alphaBits )
continue;
// check depth bits
if( current->cDepthBits < depthBits )
continue;
// check stencil bits
if( current->cStencilBits < stencilBits )
continue;
// if we don't have a selected PFD yet, then use it
if( !pixelFormat )
{
selected = current;
pixelFormat = i;
continue;
}
if( colorBits != selected->cColorBits )
{
if( colorBits == current->cColorBits || current->cColorBits > selected->cColorBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
if( alphaBits != selected->cAlphaBits )
{
if( alphaBits == current->cAlphaBits || current->cAlphaBits > selected->cAlphaBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
if( depthBits != selected->cDepthBits )
{
if( depthBits == current->cDepthBits || current->cDepthBits > selected->cDepthBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
if( stencilBits != selected->cStencilBits )
{
if( stencilBits == current->cStencilBits || current->cStencilBits > selected->cStencilBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
}
pixelFormat = pwglChoosePixelFormat( glw_state.hDC, pfd );
else pixelFormat = ChoosePixelFormat( glw_state.hDC, pfd );
if( !pixelFormat )
{
MsgDev( D_ERROR, "VID_ChoosePFD: no hardware acceleration found\n" );
MsgDev( D_ERROR, "VID_ChoosePFD failed\n" );
return 0;
}
if( selected->dwFlags & PFD_GENERIC_FORMAT )
{
if( selected->dwFlags & PFD_GENERIC_ACCELERATED )
{
MsgDev( D_NOTE, "VID_ChoosePFD: usign Generic MCD acceleration\n" );
glw_state.software = false;
}
else
{
MsgDev( D_NOTE, "VID_ChoosePFD: using software emulation\n" );
glw_state.software = true;
}
}
else
{
MsgDev( D_NOTE, "VID_ChoosePFD: using hardware acceleration\n");
glw_state.software = false;
}
return pixelFormat;
}
@ -905,8 +818,8 @@ GL_SetPixelformat
qboolean GL_SetPixelformat( void )
{
PIXELFORMATDESCRIPTOR PFD;
int colorBits, alphaBits;
int depthBits, stencilBits;
int alphaBits;
int stencilBits;
int pixelFormat;
if( glw_state.minidriver )
@ -920,21 +833,17 @@ qboolean GL_SetPixelformat( void )
return false;
}
// set color/depth/stencil
colorBits = (gl_colorbits->integer) ? gl_colorbits->integer : 32;
depthBits = (gl_depthbits->integer) ? gl_depthbits->integer : 24;
alphaBits = (gl_alphabits->integer) ? gl_alphabits->integer : 8;
stencilBits = (gl_stencilbits->integer) ? gl_stencilbits->integer : 0;
// set alpha/stencil
alphaBits = bound( 0, gl_alphabits->integer, 8 );
stencilBits = bound( 0, gl_stencilbits->integer, 8 );
// choose a pixel format
pixelFormat = VID_ChoosePFD( colorBits, alphaBits, depthBits, stencilBits );
pixelFormat = VID_ChoosePFD( &PFD, 32, alphaBits, 24, stencilBits );
if( !pixelFormat )
{
// try again with default color/depth/stencil
if( colorBits > 16 || depthBits > 16 || alphaBits > 0 || stencilBits > 0 )
pixelFormat = VID_ChoosePFD( 16, 0, 16, 0 );
else pixelFormat = VID_ChoosePFD( 32, 0, 24, 0 );
pixelFormat = VID_ChoosePFD( &PFD, 32, 0, 24, 0 );
if( !pixelFormat )
{
@ -946,23 +855,47 @@ qboolean GL_SetPixelformat( void )
// set the pixel format
if( glw_state.minidriver )
{
pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
if( !pwglSetPixelFormat( glw_state.hDC, pixelFormat, &PFD ))
{
MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" );
return false;
}
pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
}
else
{
DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
if( !SetPixelFormat( glw_state.hDC, pixelFormat, &PFD ))
{
MsgDev( D_ERROR, "GL_SetPixelformat: failed\n" );
return false;
}
DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
}
if( PFD.dwFlags & PFD_GENERIC_FORMAT )
{
if( PFD.dwFlags & PFD_GENERIC_ACCELERATED )
{
MsgDev( D_NOTE, "VID_ChoosePFD: usign Generic MCD acceleration\n" );
glw_state.software = false;
}
else if( gl_allow_software->integer )
{
MsgDev( D_NOTE, "VID_ChoosePFD: using software emulation\n" );
glw_state.software = true;
}
else
{
MsgDev( D_ERROR, "GL_SetPixelformat: no hardware acceleration found\n" );
return false;
}
}
else
{
MsgDev( D_NOTE, "VID_ChoosePFD: using hardware acceleration\n");
glw_state.software = false;
}
glConfig.color_bits = PFD.cColorBits;
@ -999,7 +932,6 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
{
WNDCLASS wc;
RECT rect;
convar_t *r_xpos, *r_ypos;
int x = 0, y = 0, w, h;
int stylebits = WINDOW_STYLE;
int exstyle = WINDOW_EX_STYLE;
@ -1057,8 +989,6 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
if( !fullscreen )
{
r_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" );
r_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" );
x = r_xpos->integer;
y = r_ypos->integer;
@ -1087,7 +1017,7 @@ qboolean VID_CreateWindow( int width, int height, qboolean fullscreen )
MsgDev( D_ERROR, "VID_CreateWindow: couldn't create '%s'\n", wndname );
return false;
}
ShowWindow( host.hWnd, SW_SHOW );
UpdateWindow( host.hWnd );
@ -1181,6 +1111,9 @@ rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen )
if( vid_displayfrequency->integer > 0 )
{
if( vid_displayfrequency->integer < 60 ) Cvar_SetFloat( "vid_displayfrequency", 60 );
if( vid_displayfrequency->integer > 100 ) Cvar_SetFloat( "vid_displayfrequency", 100 );
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = vid_displayfrequency->integer;
}
@ -1198,11 +1131,8 @@ rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen )
dm.dmPelsWidth = width * 2;
dm.dmPelsHeight = height;
dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
if( gl_depthbits->integer != 0 )
{
dm.dmBitsPerPel = gl_depthbits->integer;
dm.dmFields |= DM_BITSPERPEL;
}
dm.dmBitsPerPel = 24;
dm.dmFields |= DM_BITSPERPEL;
// our first CDS failed, so maybe we're running on some weird dual monitor system
if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
@ -1245,8 +1175,6 @@ qboolean VID_SetMode( void )
qboolean fullscreen;
fullscreen = vid_fullscreen->integer;
vid_fullscreen->modified = false;
vid_mode->modified = false;
if(( err = R_ChangeDisplaySettings( vid_mode->integer, fullscreen )) == rserr_ok )
{
@ -1257,7 +1185,6 @@ qboolean VID_SetMode( void )
if( err == rserr_invalid_fullscreen )
{
Cvar_SetFloat( "fullscreen", 0 );
vid_fullscreen->modified = false;
MsgDev( D_ERROR, "VID_SetMode: fullscreen unavailable in this mode\n" );
if(( err = R_ChangeDisplaySettings( vid_mode->integer, false )) == rserr_ok )
return true;
@ -1266,7 +1193,6 @@ qboolean VID_SetMode( void )
{
Cvar_SetFloat( "vid_mode", glConfig.prev_mode );
MsgDev( D_ERROR, "VID_SetMode: invalid mode\n" );
vid_mode->modified = false;
}
// try setting it back to something safe
@ -1288,7 +1214,7 @@ check vid modes and fullscreen
*/
void VID_CheckChanges( void )
{
if( vid_fullscreen->modified || vid_mode->modified )
if( renderinfo->modified )
{
if( !VID_SetMode())
{
@ -1297,8 +1223,7 @@ void VID_CheckChanges( void )
}
else
{
vid_fullscreen->modified = false;
vid_mode->modified = false;
renderinfo->modified = false;
SCR_VidInit(); // tell the client.dll what vid_mode has changed
}
}
@ -1366,9 +1291,6 @@ static void GL_SetDefaults( void )
pglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
}
// enable gouraud shading
pglShadeModel( GL_SMOOTH );
pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
pglPolygonOffset( -1, -2 );
@ -1448,6 +1370,7 @@ void GL_InitCommands( void )
// system screen width and height (don't suppose for change from console at all)
r_width = Cvar_Get( "width", "640", CVAR_READ_ONLY, "screen width" );
r_height = Cvar_Get( "height", "480", CVAR_READ_ONLY, "screen height" );
renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
r_speeds = Cvar_Get( "r_speeds", "0", CVAR_ARCHIVE, "shows renderer speeds" );
r_fullbright = Cvar_Get( "r_fullbright", "0", CVAR_CHEAT, "disable lightmaps, get fullbright for entities" );
r_norefresh = Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" );
@ -1468,21 +1391,21 @@ void GL_InitCommands( void )
r_drawentities = Cvar_Get( "r_drawentities", "1", CVAR_CHEAT|CVAR_ARCHIVE, "render entities" );
r_lefthand = Cvar_Get( "hand", "0", CVAR_ARCHIVE, "viewmodel handedness" );
r_decals = Cvar_Get( "r_decals", "4096", CVAR_ARCHIVE, "sets the maximum number of decals" );
gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of textures by powers of 2" );
gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "reduces resolution of skybox textures by powers of 2" );
r_xpos = Cvar_Get( "r_xpos", "130", CVAR_GLCONFIG, "window position by horizontal" );
r_ypos = Cvar_Get( "r_ypos", "48", CVAR_GLCONFIG, "window position by vertical" );
gl_picmip = Cvar_Get( "gl_picmip", "0", CVAR_GLCONFIG, "reduces resolution of textures by powers of 2" );
gl_skymip = Cvar_Get( "gl_skymip", "0", CVAR_GLCONFIG, "reduces resolution of skybox textures by powers of 2" );
gl_ignorehwgamma = Cvar_Get( "gl_ignorehwgamma", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "ignore hardware gamma (e.g. not support)" );
gl_allow_software = Cvar_Get( "gl_allow_software", "0", CVAR_ARCHIVE, "allow OpenGL software emulation" );
gl_colorbits = Cvar_Get( "gl_colorbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat color bits (0 - auto)" );
gl_alphabits = Cvar_Get( "gl_alphabits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat alpha bits (0 - auto)" );
gl_depthbits = Cvar_Get( "gl_depthbits", "0", CVAR_ARCHIVE | CVAR_LATCH_VIDEO, "pixelformat depth bits (0 - auto)" );
gl_alphabits = Cvar_Get( "gl_alphabits", "8", CVAR_GLCONFIG, "pixelformat alpha bits (0 - auto)" );
gl_texturemode = Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, "texture filter" );
gl_texturebits = Cvar_Get( "gl_texturebits", "0", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "set texture upload format (0 - auto)" );
gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_RENDERINFO, "down size non-power of two textures" );
gl_stencilbits = Cvar_Get( "gl_stencilbits", "8", CVAR_ARCHIVE|CVAR_LATCH_VIDEO, "pixelformat stencil bits (0 - auto)" );
gl_texturebits = Cvar_Get( "gl_texturebits", "0", CVAR_GLCONFIG, "set texture upload format (0 - auto)" );
gl_round_down = Cvar_Get( "gl_round_down", "0", CVAR_GLCONFIG, "down size non-power of two textures" );
gl_stencilbits = Cvar_Get( "gl_stencilbits", "8", CVAR_GLCONFIG, "pixelformat stencil bits (0 - auto)" );
gl_check_errors = Cvar_Get( "gl_check_errors", "1", CVAR_ARCHIVE, "ignore video engine errors" );
gl_swapInterval = Cvar_Get( "gl_swapInterval", "0", CVAR_ARCHIVE, "time beetween frames (in msec)" );
gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_RENDERINFO, "allow gl_extensions" );
gl_extensions = Cvar_Get( "gl_extensions", "1", CVAR_GLCONFIG, "allow gl_extensions" );
gl_texture_anisotropy = Cvar_Get( "r_anisotropy", "2.0", CVAR_ARCHIVE, "textures anisotropic filter" );
gl_nobind = Cvar_Get( "gl_nobind", "0", 0, "replace all textures with '*notexture' (perfomance test)" );
gl_texture_lodbias = Cvar_Get( "gl_texture_lodbias", "0.0", CVAR_ARCHIVE, "LOD bias for mipmapped textures" );
@ -1496,9 +1419,9 @@ void GL_InitCommands( void )
gl_swapInterval->modified = true;
vid_gamma = Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE, "gamma amount" );
vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_ARCHIVE, "display resolution mode" );
vid_mode = Cvar_Get( "vid_mode", VID_DEFAULTMODE, CVAR_RENDERINFO, "display resolution mode" );
vid_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO, "set in 1 to enable fullscreen mode" );
vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "fullscreen refresh rate" );
vid_displayfrequency = Cvar_Get ( "vid_displayfrequency", "0", CVAR_RENDERINFO, "fullscreen refresh rate" );
Cmd_AddCommand( "r_info", R_RenderInfo_f, "display renderer info" );
Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" );
@ -1696,6 +1619,7 @@ qboolean R_Init( void )
return false;
}
renderinfo->modified = false;
r_temppool = Mem_AllocPool( "Render Zone" );
GL_InitExtensions();

View File

@ -933,8 +933,6 @@ qboolean S_Init( void )
return false;
}
Cmd_ExecuteString( "sndlatch\n" );
s_volume = Cvar_Get( "volume", "0.7", CVAR_ARCHIVE, "sound volume" );
s_musicvolume = Cvar_Get( "musicvolume", "1.0", CVAR_ARCHIVE, "background music volume" );
s_mixahead = Cvar_Get( "_snd_mixahead", "0.1", CVAR_ARCHIVE, "how much sound to mix ahead of time" );

View File

@ -838,16 +838,10 @@ void MIX_MixPaintbuffers( int ibuf1, int ibuf2, int ibuf3, int count, float fgai
// mix front channels
for( i = 0; i < count; i++ )
{
pbuf3[i].left = pbuf1[i].left + pbuf2[i].left;
pbuf3[i].right = pbuf1[i].right + pbuf2[i].right;
}
if( gain == 256 ) return;
for( i = 0; i < count; i++ )
{
pbuf3[i].left = (pbuf3[i].left * gain) >> 8;
pbuf3[i].right = (pbuf3[i].right * gain) >> 8;
pbuf3[i].left = pbuf1[i].left;
pbuf3[i].right = pbuf1[i].right;
pbuf3[i].left += (pbuf2[i].left * gain) >> 8;
pbuf3[i].right += (pbuf2[i].right * gain) >> 8;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@ typedef struct
typedef struct
{
int version; // map version
uint checksum; // map checksum
uint checksum; // current map checksum
int load_sequence; // increace each map change
vec3_t hull_sizes[4]; // actual hull sizes
msurface_t **draw_surfaces; // used for sorting translucent surfaces

View File

@ -83,6 +83,7 @@ void Mod_UnloadStudioModel( struct model_s *mod );
void Mod_UnloadBrushModel( struct model_s *mod );
void GL_SetRenderMode( int mode );
void R_RunViewmodelEvents( void );
void R_DrawViewModel( void );
int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame );
void R_LightForPoint( const vec3_t point, color24 *ambientLight, qboolean invLight, float radius );
void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, vec3_t saxis );

View File

@ -161,6 +161,7 @@ void Host_EndGame( const char *message, ... );
void Host_AbortCurrentFrame( void );
void Host_WriteServerConfig( const char *name );
void Host_WriteOpenGLConfig( void );
void Host_WriteVideoConfig( void );
void Host_WriteConfig( void );
qboolean Host_IsLocalGame( void );
void Host_ShutdownServer( void );

View File

@ -796,6 +796,12 @@ static void Cmd_WriteServerCvar(const char *name, const char *string, const char
}
static void Cmd_WriteOpenGLCvar( const char *name, const char *string, const char *desc, void *f )
{
if( !desc || !*desc ) return; // ignore cvars without description (fantom variables)
FS_Printf( f, "setgl %s \"%s\"\n", name, string );
}
static void Cmd_WriteRenderCvar( const char *name, const char *string, const char *desc, void *f )
{
if( !desc || !*desc ) return; // ignore cvars without description (fantom variables)
FS_Printf( f, "setr %s \"%s\"\n", name, string );
@ -821,7 +827,12 @@ void Cmd_WriteServerVariables( file_t *f )
void Cmd_WriteOpenGLVariables( file_t *f )
{
Cvar_LookupVars( CVAR_RENDERINFO, NULL, f, Cmd_WriteOpenGLCvar );
Cvar_LookupVars( CVAR_GLCONFIG, NULL, f, Cmd_WriteOpenGLCvar );
}
void Cmd_WriteRenderVariables( file_t *f )
{
Cvar_LookupVars( CVAR_RENDERINFO, NULL, f, Cmd_WriteRenderCvar );
}
/*
@ -892,7 +903,7 @@ void Host_WriteServerConfig( const char *name )
===============
Host_WriteOpenGLConfig
save renderinfo variables into opengl.cfg
save opengl variables into opengl.cfg
===============
*/
void Host_WriteOpenGLConfig( void )
@ -912,6 +923,30 @@ void Host_WriteOpenGLConfig( void )
else MsgDev( D_ERROR, "can't update opengl.cfg.\n" );
}
/*
===============
Host_WriteVideoConfig
save render variables into video.cfg
===============
*/
void Host_WriteVideoConfig( void )
{
file_t *f;
f = FS_Open( "video.cfg", "w" );
if( f )
{
FS_Printf( f, "//=======================================================================\n" );
FS_Printf( f, "//\t\t\tCopyright XashXT Group %s ©\n", timestamp( TIME_YEAR_ONLY ));
FS_Printf( f, "//\t\tvideo.cfg - archive of renderer variables\n");
FS_Printf( f, "//=======================================================================\n" );
Cmd_WriteRenderVariables( f );
FS_Close( f );
}
else MsgDev( D_ERROR, "can't update video.cfg.\n" );
}
void Key_EnumCmds_f( void )
{
file_t *f;

View File

@ -185,12 +185,12 @@ void Con_ToggleConsole_f( void )
if( cls.key_dest == key_console )
{
UI_SetActiveMenu( false );
cls.key_dest = key_game;
Key_SetKeyDest( key_game );
}
else
{
UI_SetActiveMenu( false );
cls.key_dest = key_console;
Key_SetKeyDest( key_console );
}
}
@ -406,7 +406,7 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
static int Con_DrawCharacter( int x, int y, int number, rgba_t color )
{
GL_SetRenderMode( kRenderTransTexture );
GL_SetRenderMode( kRenderNormal );
return Con_DrawGenericChar( x, y, number, color );
}
@ -1409,7 +1409,7 @@ void Con_DrawConsole( void )
if( cls.key_dest != key_menu && host.developer )
{
Con_DrawSolidConsole( 1.0f );
cls.key_dest = key_console;
Key_SetKeyDest( key_console );
}
break;
case ca_connected:

View File

@ -18,8 +18,6 @@ convar_t *host_limitlocal;
convar_t *host_cheats;
convar_t *host_maxfps;
convar_t *host_framerate;
qboolean sound_restart;
qboolean video_restart;
// these cvars will be duplicated on each client across network
int Host_ServerState( void )
@ -118,30 +116,6 @@ void Host_SetServerState( int state )
Cvar_FullSet( "host_serverstate", va( "%i", state ), CVAR_INIT );
}
/*
=================
Host_VidRestart_f
Restart the video subsystem
=================
*/
void Host_VidRestart_f( void )
{
video_restart = true;
}
/*
=================
Host_SndRestart_f
Restart the audio subsystem
=================
*/
void Host_SndRestart_f( void )
{
sound_restart = true;
}
/*
=================
Host_ChangeGame_f
@ -611,18 +585,16 @@ void Host_Init( const int argc, const char **argv )
host_limitlocal = Cvar_Get( "host_limitlocal", "0", 0, "apply cl_cmdrate and rate to loopback connection" );
// content control
Cvar_Get( "violence_hgibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables human gibs" );
Cvar_Get( "violence_agibs", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables alien gibs" );
Cvar_Get( "violence_hblood", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables human blood" );
Cvar_Get( "violence_ablood", "1", CVAR_INIT|CVAR_ARCHIVE, "content control disables alien blood" );
video_restart = true; // initalize renderer
sound_restart = true; // initialize sound engine
Cvar_Get( "violence_hgibs", "1", CVAR_ARCHIVE, "show human gib entities" );
Cvar_Get( "violence_agibs", "1", CVAR_ARCHIVE, "show alien gib entities" );
Cvar_Get( "violence_hblood", "1", CVAR_ARCHIVE, "draw human blood" );
Cvar_Get( "violence_ablood", "1", CVAR_ARCHIVE, "draw alien blood" );
if( host.type != HOST_DEDICATED )
{
// when we in developer-mode automatically turn cheats on
if( host.developer > 1 ) Cvar_SetFloat( "sv_cheats", 1.0f );
Cbuf_AddText( "exec video.cfg\n" );
}
Mod_Init();
@ -647,8 +619,6 @@ void Host_Init( const int argc, const char **argv )
else
{
Cmd_AddCommand( "minimize", Host_Minimize_f, "minimize main window to tray" );
Cmd_AddCommand( "vid_restart", Host_VidRestart_f, "restarts video system" );
Cmd_AddCommand( "snd_restart", Host_SndRestart_f, "restarts audio system" );
Cbuf_AddText( "exec config.cfg\n" );
}

View File

@ -32,10 +32,6 @@ RECT window_rect, real_rect;
uint in_mouse_wheel;
int wnd_caption;
convar_t *scr_xpos; // X coordinate of window position
convar_t *scr_ypos; // Y coordinate of window position
convar_t *scr_fullscreen;
static byte scan_to_key[128] =
{
0,27,'1','2','3','4','5','6','7','8','9','0','-','=',K_BACKSPACE,9,
@ -188,7 +184,7 @@ void IN_ActivateMouse( void )
if( !in_mouseinitialized )
return;
if( cls.key_dest == key_menu && !scr_fullscreen->integer )
if( cls.key_dest == key_menu && !Cvar_VariableInteger( "fullscreen" ))
{
// check for mouse leave-entering
if( !in_mouse_suspended && !UI_MouseInRect( ))
@ -439,7 +435,7 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
switch( uMsg )
{
case WM_KILLFOCUS:
if( scr_fullscreen && scr_fullscreen->integer )
if( Cvar_VariableInteger( "fullscreen" ))
ShowWindow( host.hWnd, SW_SHOWMINNOACTIVE );
break;
case WM_MOUSEWHEEL:
@ -457,9 +453,6 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
break;
case WM_CREATE:
host.hWnd = hWnd;
scr_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" );
scr_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" );
scr_fullscreen = Cvar_Get( "fullscreen", "0", CVAR_RENDERINFO|CVAR_LATCH_VIDEO, "toggle fullscreen" );
GetWindowRect( host.hWnd, &real_rect );
break;
case WM_CLOSE:
@ -486,13 +479,13 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
SetForegroundWindow( hWnd );
ShowWindow( hWnd, SW_RESTORE );
}
else if( scr_fullscreen->integer && host.state != HOST_RESTART )
else if( Cvar_VariableInteger( "fullscreen" ) && host.state != HOST_RESTART )
{
ShowWindow( hWnd, SW_MINIMIZE );
}
break;
case WM_MOVE:
if( !scr_fullscreen->integer )
if( !Cvar_VariableInteger( "fullscreen" ))
{
RECT rect;
int xPos, yPos, style;
@ -507,8 +500,6 @@ long IN_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
Cvar_SetFloat( "r_xpos", xPos + rect.left );
Cvar_SetFloat( "r_ypos", yPos + rect.top );
scr_xpos->modified = false;
scr_ypos->modified = false;
GetWindowRect( host.hWnd, &real_rect );
}
break;

View File

@ -538,7 +538,7 @@ void Key_Event( int key, qboolean down )
case key_console:
if( cls.state == ca_active )
{
cls.key_dest = key_game;
Key_SetKeyDest( key_game );
}
else
{

View File

@ -857,6 +857,9 @@ static void Mod_LoadSurfaces( const dlump_t *l )
if( com.stristr( tex->name, "scroll" ))
out->flags |= SURF_CONVEYOR;
if( tex->name[0] == '{' )
out->flags |= SURF_TRANSPARENT;
if( out->texinfo->flags & TEX_SPECIAL )
out->flags |= SURF_DRAWTILED;
}
@ -1605,13 +1608,13 @@ Mod_LoadModel
Loads a model into the cache
==================
*/
model_t *Mod_LoadModel( model_t *mod, qboolean isWorld )
model_t *Mod_LoadModel( model_t *mod, qboolean crash )
{
byte *buf;
if( !mod )
{
if( isWorld ) Host_Error( "Mod_ForName: NULL model\n" );
if( crash ) Host_Error( "Mod_ForName: NULL model\n" );
else MsgDev( D_ERROR, "Mod_ForName: NULL model\n" );
return NULL;
}
@ -1623,16 +1626,12 @@ model_t *Mod_LoadModel( model_t *mod, qboolean isWorld )
buf = FS_LoadFile( mod->name, NULL );
if( !buf )
{
if( isWorld ) Host_Error( "Mod_ForName: %s couldn't load\n", mod->name );
if( crash ) Host_Error( "Mod_ForName: %s couldn't load\n", mod->name );
else MsgDev( D_ERROR, "Mod_ForName: %s couldn't load\n", mod->name );
Mem_Set( mod, 0, sizeof( model_t ));
return NULL;
}
// if it's world - calc the map checksum
if( isWorld ) CRC32_MapFile( &world.checksum, mod->name );
world.loading = isWorld;
MsgDev( D_NOTE, "Mod_LoadModel: %s\n", mod->name );
mod->needload = world.load_sequence; // register mod
mod->type = mod_bad;
@ -1660,7 +1659,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean isWorld )
Mod_FreeModel( mod );
// check for loading problems
if( isWorld ) Host_Error( "Mod_ForName: %s unknown format\n", mod->name );
if( crash ) Host_Error( "Mod_ForName: %s unknown format\n", mod->name );
else MsgDev( D_ERROR, "Mod_ForName: %s unknown format\n", mod->name );
return NULL;
}
@ -1674,12 +1673,12 @@ Mod_ForName
Loads in a model for the given name
==================
*/
model_t *Mod_ForName( const char *name, qboolean world )
model_t *Mod_ForName( const char *name, qboolean crash )
{
model_t *mod;
mod = Mod_FindName( name, true );
return Mod_LoadModel( mod, world );
return Mod_LoadModel( mod, crash );
}
/*
@ -1720,10 +1719,14 @@ void Mod_LoadWorld( const char *name, uint *checksum )
world.load_sequence++; // now all models are invalid
// load the newmap
world.loading = true;
worldmodel = Mod_ForName( name, true );
com_models[1] = cm_models; // make link to world
if( checksum ) *checksum = world.checksum;
CRC32_MapFile( &world.checksum, worldmodel->name );
world.loading = false;
if( checksum ) *checksum = world.checksum;
// calc Potentially Hearable Set and compress it
Mod_CalcPHS();
}

View File

@ -413,7 +413,7 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags,
{
if( !com.strcmp( pField->name, pName ))
{
MsgDev( D_ERROR, "Delta_Add: %s->%s already existing\n", pStructName, pName );
MsgDev( D_NOTE, "Delta_Add: %s->%s already existing\n", pStructName, pName );
return false; // field already exist
}
}
@ -743,6 +743,9 @@ void Delta_InitFields( void )
// adding some requrid fields fields that use may forget or don't know how to specified
Delta_AddField( "event_t", "flags", DT_INTEGER, 8, 1.0f, 1.0f );
Delta_AddField( "event_t", "velocity[0]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[1]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[2]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
}
void Delta_Init( void )

View File

@ -377,6 +377,7 @@ extern convar_t *sv_allow_upload;
extern convar_t *sv_allow_download;
extern convar_t *sv_send_resources;
extern convar_t *sv_send_logos;
extern convar_t *sv_sendvelocity;
extern convar_t *mp_consistency;
extern convar_t *physinfo;
extern sv_client_t *sv_client;

View File

@ -1480,13 +1480,7 @@ int pfnDropToFloor( edict_t* e )
VectorCopy( e->v.origin, end );
end[2] -= 256;
#if 1
if( e->v.solid == SOLID_TRIGGER || e->v.solid == SOLID_NOT )
trace = SV_Move( e->v.origin, vec3_origin, vec3_origin, end, MOVE_NOMONSTERS, e );
else trace = SV_Move( e->v.origin, e->v.mins, e->v.maxs, end, MOVE_NORMAL, e );
#else
trace = SV_Move( e->v.origin, e->v.mins, e->v.maxs, end, MOVE_NORMAL, e );
#endif
if( trace.allsolid )
return -1;
@ -3565,7 +3559,8 @@ void SV_PlaybackEventFull( int flags, const edict_t *pInvoker, word eventindex,
// silently replace it with viewangles, client expected this
VectorCopy( pInvoker->v.v_angle, args.angles );
}
VectorCopy( pInvoker->v.velocity, args.velocity );
if( sv_sendvelocity->integer ) VectorCopy( pInvoker->v.velocity, args.velocity );
args.ducking = (pInvoker->v.flags & FL_DUCKING) ? true : false;
}

View File

@ -52,6 +52,7 @@ convar_t *sv_allow_upload;
convar_t *sv_allow_download;
convar_t *sv_send_resources;
convar_t *sv_send_logos;
convar_t *sv_sendvelocity;
convar_t *mp_consistency;
convar_t *serverinfo;
convar_t *physinfo;
@ -644,6 +645,7 @@ void SV_Init( void )
sv_allow_download = Cvar_Get( "sv_allow_download", "1", 0, "allow download missed resources to clients" );
sv_send_logos = Cvar_Get( "sv_send_logos", "1", 0, "send custom player decals to other clients" );
sv_send_resources = Cvar_Get( "sv_send_resources", "1", 0, "send generic resources that specified in 'mapname.res'" );
sv_sendvelocity = Cvar_Get( "sv_sendvelocity", "1", CVAR_ARCHIVE, "force to send velocity for event_t structure across network" );
mp_consistency = Cvar_Get( "mp_consistency", "1", CVAR_SERVERNOTIFY, "enbale consistency check in multiplayer" );
clockwindow = Cvar_Get( "clockwindow", "0.5", 0, "timewindow to execute client moves" );
sv_novis = Cvar_Get( "sv_novis", "0", 0, "force to ignore server visibility" );

View File

@ -421,7 +421,7 @@ void ReapplyDecal( SAVERESTOREDATA *pSaveData, decallist_t *entry, qboolean adja
edict_t *pEdict = pSaveData->pTable[entry->entityIndex].pent;
if( pEdict != NULL ) modelIndex = pEdict->v.modelindex;
SV_CreateDecal( entry->position, decalIndex, entry->entityIndex, modelIndex, flags );
SV_CreateDecal( entry->position, decalIndex, pEdict->serialnumber, modelIndex, flags );
}
}

View File

@ -227,6 +227,7 @@ qboolean CRC32_MapFile( dword *crcvalue, const char *filename )
int i, num_bytes, lumplen;
qboolean blue_shift = false;
if( !crcvalue ) return false;
f = FS_Open( filename, "rb", false );
if( !f ) return false;

View File

@ -6,7 +6,7 @@
#include "launch.h"
convar_t *cvar_vars; // head of list
convar_t *userinfo, *physinfo, *serverinfo;
convar_t *userinfo, *physinfo, *serverinfo, *renderinfo;
/*
============
@ -345,7 +345,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
if( !force )
{
if( var->flags & CVAR_READ_ONLY )
if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG ))
{
MsgDev( D_INFO, "%s is read only.\n", var_name );
return var;
@ -357,13 +357,7 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
return var;
}
if( var->flags & CVAR_RENDERINFO )
{
MsgDev( D_INFO, "%s is a renderer config variable.\n", var_name );
return var;
}
if( var->flags & ( CVAR_LATCH|CVAR_LATCH_VIDEO|CVAR_LATCH_AUDIO ))
if( var->flags & ( CVAR_LATCH|CVAR_LATCH_VIDEO ))
{
if( var->latched_string )
{
@ -387,11 +381,6 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
MsgDev( D_INFO, "%s will be changed upon restarting video.\n", var->name );
var->latched_string = copystring( value );
}
else if( var->flags & CVAR_LATCH_AUDIO )
{
MsgDev( D_INFO, "%s will be changed upon restarting audio.\n", var->name );
var->latched_string = copystring( value );
}
else
{
Mem_Free( var->string ); // free the old value string
@ -472,6 +461,8 @@ convar_t *Cvar_Set2( const char *var_name, const char *value, qboolean force )
if( var->flags & CVAR_SERVERINFO )
serverinfo->modified = true; // transmit at next oportunity
if( var->flags & CVAR_RENDERINFO )
renderinfo->modified = true; // transmit at next oportunity
// free the old value string
Mem_Free( var->string );
@ -550,6 +541,12 @@ void Cvar_FullSet( const char *var_name, const char *value, int flags )
serverinfo->modified = true;
}
if( var->flags & CVAR_RENDERINFO )
{
// transmit at next oportunity
renderinfo->modified = true;
}
Mem_Free( var->string ); // free the old value string
var->string = copystring( value );
var->value = com.atof( var->string );
@ -586,7 +583,7 @@ void Cvar_DirectSet( cvar_t *var, const char *value )
if( !value ) value = "0";
if( var->flags & ( CVAR_READ_ONLY|CVAR_INIT|CVAR_RENDERINFO|CVAR_LATCH|CVAR_LATCH_VIDEO|CVAR_LATCH_AUDIO ))
if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_LATCH|CVAR_LATCH_VIDEO ))
{
// Cvar_DirectSet cannot change these cvars at all
return;
@ -650,6 +647,9 @@ void Cvar_DirectSet( cvar_t *var, const char *value )
if( var->flags & CVAR_SERVERINFO )
serverinfo->modified = true; // transmit at next oportunity
if( var->flags & CVAR_RENDERINFO )
renderinfo->modified = true; // transmit at next oportunity
// free the old value string
Mem_Free( var->string );
var->string = copystring( pszValue );
@ -910,6 +910,23 @@ void Cvar_SetR_f( void )
Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_RENDERINFO );
}
/*
============
Cvar_SetGL_f
As Cvar_Set, but also flags it as glconfig
============
*/
void Cvar_SetGL_f( void )
{
if( Cmd_Argc() != 3 )
{
Msg( "Usage: setgl <variable> <value>\n" );
return;
}
Cvar_FullSet( Cmd_Argv( 1 ), Cmd_Argv( 2 ), CVAR_GLCONFIG );
}
/*
============
@ -945,34 +962,34 @@ void Cvar_List_f( void )
if( match && !com.stricmpext( match, var->name ))
continue;
if( var->flags & CVAR_SERVERINFO ) Msg( "SV " );
if( var->flags & CVAR_SERVERINFO ) Msg( "SV " );
else Msg( " " );
if( var->flags & CVAR_USERINFO ) Msg( "USER " );
if( var->flags & CVAR_USERINFO ) Msg( "USER " );
else Msg( " " );
if( var->flags & CVAR_PHYSICINFO ) Msg( "PHYS " );
if( var->flags & CVAR_PHYSICINFO ) Msg( "PHYS " );
else Msg( " " );
if( var->flags & CVAR_READ_ONLY ) Msg( "READ " );
if( var->flags & CVAR_READ_ONLY ) Msg( "READ " );
else Msg( " " );
if( var->flags & CVAR_INIT ) Msg( "INIT " );
if( var->flags & CVAR_INIT ) Msg( "INIT " );
else Msg( " " );
if( var->flags & CVAR_ARCHIVE ) Msg( "ARCH " );
if( var->flags & CVAR_ARCHIVE ) Msg( "ARCH " );
else Msg( " " );
if( var->flags & CVAR_LATCH ) Msg( "LATCH" );
if( var->flags & CVAR_LATCH ) Msg( "LATCH " );
else Msg( " " );
if( var->flags & CVAR_LATCH_VIDEO ) Msg( "VIDEO" );
if( var->flags & CVAR_LATCH_VIDEO ) Msg( "VIDEO " );
else Msg( " " );
if( var->flags & CVAR_LATCH_AUDIO ) Msg( "AUDIO" );
if( var->flags & CVAR_GLCONFIG ) Msg( "OPENGL" );
else Msg( " " );
if( var->flags & CVAR_CHEAT ) Msg( "CHEAT" );
if( var->flags & CVAR_CHEAT ) Msg( "CHEAT " );
else Msg( " " );
Msg(" %s \"%s\"\n", var->name, var->string );
j++;
@ -1003,7 +1020,7 @@ void Cvar_Restart_f( void )
// don't mess with rom values, or some inter-module
// communication will get broken (cl.active, etc)
if( var->flags & ( CVAR_READ_ONLY|CVAR_INIT|CVAR_RENDERINFO|CVAR_EXTDLL ))
if( var->flags & ( CVAR_READ_ONLY|CVAR_GLCONFIG|CVAR_INIT|CVAR_RENDERINFO|CVAR_EXTDLL ))
{
prev = &var->next;
continue;
@ -1098,41 +1115,6 @@ void Cvar_LatchedVideo_f( void )
}
}
/*
============
Cvar_Latched_f
Now all latched audio strings is valid
============
*/
void Cvar_LatchedAudio_f( void )
{
convar_t *var;
convar_t **prev;
prev = &cvar_vars;
while ( 1 )
{
var = *prev;
if( !var ) break;
if( var->flags & CVAR_EXTDLL )
{
prev = &var->next;
continue;
}
if( var->flags & CVAR_LATCH_AUDIO && var->latched_string )
{
Cvar_FullSet( var->name, var->latched_string, var->flags );
Mem_Free( var->latched_string );
var->latched_string = NULL;
}
prev = &var->next;
}
}
/*
============
Cvar_Unlink_f
@ -1186,6 +1168,7 @@ void Cvar_Init( void )
userinfo = Cvar_Get( "@userinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
physinfo = Cvar_Get( "@physinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
serverinfo = Cvar_Get( "@serverinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
renderinfo = Cvar_Get( "@renderinfo", "0", CVAR_READ_ONLY, "" ); // use ->modified value only
Cmd_AddCommand ("toggle", Cvar_Toggle_f, "toggles a console variable's values (use for more info)" );
Cmd_AddCommand ("set", Cvar_Set_f, "create or change the value of a console variable" );
@ -1193,11 +1176,11 @@ void Cvar_Init( void )
Cmd_AddCommand ("setu", Cvar_SetU_f, "create or change the value of a userinfo variable" );
Cmd_AddCommand ("setp", Cvar_SetP_f, "create or change the value of a physicinfo variable" );
Cmd_AddCommand ("setr", Cvar_SetR_f, "create or change the value of a renderinfo variable" );
Cmd_AddCommand ("setgl", Cvar_SetGL_f, "create or change the value of a opengl variable" );
Cmd_AddCommand ("seta", Cvar_SetA_f, "create or change the value of a console variable that will be saved to config.cfg" );
Cmd_AddCommand ("reset", Cvar_Reset_f, "reset any type variable to initial value" );
Cmd_AddCommand ("latch", Cvar_Latched_f, "apply latched values" );
Cmd_AddCommand ("vidlatch", Cvar_LatchedVideo_f, "apply latched values for video subsystem" );
Cmd_AddCommand ("sndlatch", Cvar_LatchedAudio_f, "apply latched values for audio subsytem" );
Cmd_AddCommand ("cvarlist", Cvar_List_f, "display all console variables beginning with the specified prefix" );
Cmd_AddCommand ("unsetall", Cvar_Restart_f, "reset all console variables to their default values" );
Cmd_AddCommand ("@unlink", Cvar_Unlink_f, "unlink static cvars defined in gamedll" );

View File

@ -213,6 +213,7 @@ enum
{
LUMP_NORMAL = 0,
LUMP_TRANSPARENT,
LUMP_INDEXALPHA,
LUMP_DECAL,
LUMP_QFONT,
LUMP_EXTENDED // bmp images have extened palette with alpha-channel

View File

@ -438,6 +438,16 @@ void Image_SetPalette( const byte *pal, uint *d_table )
d_table[i] = *(uint *)rgba;
}
break;
case LUMP_INDEXALPHA:
for( i = 0; i < 256; i++ )
{
rgba[0] = pal[i*3+0];
rgba[1] = pal[i*3+1];
rgba[2] = pal[i*3+2];
rgba[3] = i;
d_table[i] = *(uint *)rgba;
}
break;
case LUMP_TRANSPARENT:
for( i = 0; i < 256; i++ )
{

View File

@ -33,6 +33,8 @@ qboolean Image_LoadPAL( const char *name, const byte *buffer, size_t filesize )
rendermode = LUMP_TRANSPARENT;
else if( com.stristr( name, "decal" ))
rendermode = LUMP_DECAL;
else if( com.stristr( name, "indexalpha" ))
rendermode = LUMP_INDEXALPHA;
else if( com.stristr( name, "qfont" ))
rendermode = LUMP_QFONT;
else if( com.stristr( name, "valve" ))
@ -224,7 +226,7 @@ qboolean Image_LoadSPR( const char *name, const byte *buffer, size_t filesize )
image.type = PF_INDEXED_32; // 32-bit palete
// detect alpha-channel by palette type
if( image.d_rendermode == LUMP_DECAL || image.d_rendermode == LUMP_TRANSPARENT )
if( image.d_rendermode == LUMP_INDEXALPHA || image.d_rendermode == LUMP_TRANSPARENT )
image.flags |= IMAGE_HAS_ALPHA;
// make transparent color is black, blue color looks ugly

View File

@ -491,6 +491,7 @@ void Sys_CreateInstance( void )
}
Cmd_RemoveCommand( "setr" ); // remove potentially backdoor for change render settings
Cmd_RemoveCommand( "setgl" );
Sys.app_state = SYS_FRAME; // system is now active
}

View File

@ -807,7 +807,16 @@ void UI_PopMenu( void )
uiStatic.menuActive = uiStatic.menuStack[uiStatic.menuDepth-1];
uiStatic.firstDraw = true;
}
else UI_CloseMenu();
else if ( CL_IsActive( ))
{
UI_CloseMenu();
}
else
{
// never trying the close menu when client isn't connected
KEY_SetDest( KEY_MENU );
UI_Main_Menu();
}
}
// =====================================================================
@ -1244,6 +1253,16 @@ int UI_VidInit( void )
// register ui font
uiStatic.hFont = PIC_Load( "menufont", font_tga, sizeof( font_tga ));
// now recalc all the menus in stack
for( int i = 0; i < uiStatic.menuDepth; i++ )
{
menuFramework_s *item = uiStatic.menuStack[i];
// do vid restart for all pushed elements
if( item && item->vidInitFunc )
item->vidInitFunc();
}
return 1;
}

View File

@ -130,6 +130,7 @@ typedef struct
void (*drawFunc)( void );
const char *(*keyFunc)( int key, int down );
void (*activateFunc)( void );
void (*vidInitFunc)( void );
} menuFramework_s;
typedef struct

View File

@ -182,6 +182,8 @@ static void UI_AdvControls_Init( void )
{
memset( &uiAdvControls, 0, sizeof( uiAdvControls_t ));
uiAdvControls.menu.vidInitFunc = UI_AdvControls_Init;
uiAdvControls.background.generic.id = ID_BACKGROUND;
uiAdvControls.background.generic.type = QMTYPE_BITMAP;
uiAdvControls.background.generic.flags = QMF_INACTIVE;

View File

@ -124,8 +124,6 @@ static void UI_Audio_SetConfig( void )
CVAR_SET_FLOAT( "musicvolume", uiAudio.musicVolume.curValue );
CVAR_SET_FLOAT( "s_lerping", uiAudio.lerping.enabled );
CVAR_SET_FLOAT( "dsp_off", uiAudio.noDSP.enabled );
CLIENT_COMMAND( TRUE, "snd_restart\n" );
}
/*
@ -202,6 +200,8 @@ static void UI_Audio_Init( void )
{
memset( &uiAudio, 0, sizeof( uiAudio_t ));
uiAudio.menu.vidInitFunc = UI_Audio_Init;
strcat( uiAudio.hintText, "Change Xash3D sound engine to get more compatibility\n" );
strcat( uiAudio.hintText, "or enable new features (EAX, Filters etc)" );

View File

@ -151,6 +151,7 @@ static void UI_Options_Init( void )
{
memset( &uiOptions, 0, sizeof( uiOptions_t ));
uiOptions.menu.vidInitFunc = UI_Options_Init;
uiOptions.menu.keyFunc = UI_Options_KeyFunc;
uiOptions.background.generic.id = ID_BACKGROUND;

View File

@ -393,6 +393,7 @@ static void UI_Controls_Init( void )
{
memset( &uiControls, 0, sizeof( uiControls_t ));
uiControls.menu.vidInitFunc = UI_Controls_Init;
uiControls.menu.keyFunc = UI_Controls_KeyFunc;
StringConcat( uiControls.hintText, "Action", CMD_LENGTH );

View File

@ -261,6 +261,7 @@ static void UI_CreateGame_Init( void )
{
memset( &uiCreateGame, 0, sizeof( uiCreateGame_t ));
uiCreateGame.menu.vidInitFunc = UI_CreateGame_Init;
uiCreateGame.menu.keyFunc = UI_CreateGame_KeyFunc;
StringConcat( uiCreateGame.hintText, "Map", MAPNAME_LENGTH );

View File

@ -221,6 +221,7 @@ static void UI_CustomGame_Init( void )
{
memset( &uiCustomGame, 0, sizeof( uiCustomGame_t ));
uiCustomGame.menu.vidInitFunc = UI_CustomGame_Init;
uiCustomGame.menu.keyFunc = UI_CustomGame_KeyFunc;
StringConcat( uiCustomGame.hintText, "Type", TYPE_LENGTH );

View File

@ -179,6 +179,7 @@ static void UI_GameOptions_Init( void )
memset( &uiGameInitial, 0, sizeof( uiGameValues_t ));
memset( &uiGameOptions, 0, sizeof( uiGameOptions_t ));
uiGameOptions.menu.vidInitFunc = UI_GameOptions_Init;
uiGameOptions.menu.keyFunc = UI_GameOptions_KeyFunc;
uiGameOptions.background.generic.id = ID_BACKGROUND;

View File

@ -259,6 +259,7 @@ static void UI_LanGame_Init( void )
{
memset( &uiLanGame, 0, sizeof( uiLanGame_t ));
uiLanGame.menu.vidInitFunc = UI_LanGame_Init;
uiLanGame.menu.keyFunc = UI_LanGame_KeyFunc;
StringConcat( uiLanGame.hintText, "Game", GAME_LENGTH );

View File

@ -292,6 +292,7 @@ static void UI_LoadGame_Init( void )
{
memset( &uiLoadGame, 0, sizeof( uiLoadGame_t ));
uiLoadGame.menu.vidInitFunc = UI_LoadGame_Init;
uiLoadGame.menu.keyFunc = UI_LoadGame_KeyFunc;
StringConcat( uiLoadGame.hintText, "Time", TIME_LENGTH );

View File

@ -322,6 +322,10 @@ static void UI_Main_Init( void )
{
memset( &uiMain, 0, sizeof( uiMain_t ));
// precache .avi file and get logo width and height
PRECACHE_LOGO( "logo.avi" );
uiMain.menu.vidInitFunc = UI_Main_Init;
uiMain.menu.keyFunc = UI_Main_KeyFunc;
uiMain.menu.activateFunc = UI_Main_ActivateFunc;

View File

@ -93,6 +93,8 @@ static void UI_MultiPlayer_Init( void )
{
memset( &uiMultiPlayer, 0, sizeof( uiMultiPlayer_t ));
uiMultiPlayer.menu.vidInitFunc = UI_MultiPlayer_Init;
uiMultiPlayer.background.generic.id = ID_BACKGROUND;
uiMultiPlayer.background.generic.type = QMTYPE_BITMAP;
uiMultiPlayer.background.generic.flags = QMF_INACTIVE;

View File

@ -178,6 +178,7 @@ static void UI_NewGame_Init( void )
{
memset( &uiNewGame, 0, sizeof( uiNewGame_t ));
uiNewGame.menu.vidInitFunc = UI_NewGame_Init;
uiNewGame.menu.keyFunc = UI_NewGame_KeyFunc;
uiNewGame.background.generic.id = ID_BACKGROUND;

View File

@ -296,6 +296,7 @@ static void UI_PlayDemo_Init( void )
{
memset( &uiPlayDemo, 0, sizeof( uiPlayDemo_t ));
uiPlayDemo.menu.vidInitFunc = UI_PlayDemo_Init;
uiPlayDemo.menu.keyFunc = UI_PlayDemo_KeyFunc;
StringConcat( uiPlayDemo.hintText, "Title", TITLE_LENGTH );

View File

@ -266,6 +266,8 @@ static void UI_PlayerSetup_Init( void )
{
memset( &uiPlayerSetup, 0, sizeof( uiPlayerSetup_t ));
uiPlayerSetup.menu.vidInitFunc = UI_PlayerSetup_Init;
uiPlayerSetup.background.generic.id = ID_BACKGROUND;
uiPlayerSetup.background.generic.type = QMTYPE_BITMAP;
uiPlayerSetup.background.generic.flags = QMF_INACTIVE;

View File

@ -85,6 +85,8 @@ static void UI_PlayRec_Init( void )
{
memset( &uiPlayRec, 0, sizeof( uiPlayRec_t ));
uiPlayRec.menu.vidInitFunc = UI_PlayRec_Init;
strcat( uiPlayRec.hintText, "During play or record demo, you can quickly stop\n" );
strcat( uiPlayRec.hintText, "playing/recording demo by pressing " );
strcat( uiPlayRec.hintText, KEY_KeynumToString( KEY_GetKey( "stop" )));

View File

@ -322,6 +322,7 @@ static void UI_RecDemo_Init( void )
{
memset( &uiRecDemo, 0, sizeof( uiRecDemo_t ));
uiRecDemo.menu.vidInitFunc = UI_RecDemo_Init;
uiRecDemo.menu.keyFunc = UI_RecDemo_KeyFunc;
StringConcat( uiRecDemo.hintText, "Title", TITLE_LENGTH );

View File

@ -314,6 +314,7 @@ static void UI_SaveGame_Init( void )
{
memset( &uiSaveGame, 0, sizeof( uiSaveGame_t ));
uiSaveGame.menu.vidInitFunc = UI_SaveGame_Init;
uiSaveGame.menu.keyFunc = UI_SaveGame_KeyFunc;
StringConcat( uiSaveGame.hintText, "Time", TIME_LENGTH );

View File

@ -85,6 +85,8 @@ static void UI_SaveLoad_Init( void )
{
memset( &uiSaveLoad, 0, sizeof( uiSaveLoad_t ));
uiSaveLoad.menu.vidInitFunc = UI_SaveLoad_Init;
strcat( uiSaveLoad.hintText, "During play, you can quickly save your game by pressing " );
strcat( uiSaveLoad.hintText, KEY_KeynumToString( KEY_GetKey( "savequick" )));
strcat( uiSaveLoad.hintText, ".\nLoad this game again by pressing " );

View File

@ -80,6 +80,8 @@ static void UI_Video_Init( void )
{
memset( &uiVideo, 0, sizeof( uiVideo_t ));
uiVideo.menu.vidInitFunc = UI_Video_Init;
uiVideo.background.generic.id = ID_BACKGROUND;
uiVideo.background.generic.type = QMTYPE_BITMAP;
uiVideo.background.generic.flags = QMF_INACTIVE;

View File

@ -26,8 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define ID_BACKGROUND 0
#define ID_BANNER 1
#define ID_OK 2
#define ID_CANCEL 3
#define ID_APPLY 2
#define ID_DONE 3
#define ID_RENDERLIBRARY 4
#define ID_VIDMODELIST 5
#define ID_FULLSCREEN 6
@ -126,8 +126,6 @@ static void UI_VidOptions_SetConfig( void )
CVAR_SET_FLOAT( "vid_mode", uiVidModes.vidList.curItem );
CVAR_SET_FLOAT( "fullscreen", !uiVidModes.windowed.enabled );
CVAR_SET_FLOAT( "r_allow_software", uiVidModes.software.enabled );
CLIENT_COMMAND( TRUE, "vid_restart\n" );
}
/*
@ -171,10 +169,10 @@ static void UI_VidModes_Callback( void *self, int event )
switch( item->id )
{
case ID_CANCEL:
case ID_DONE:
UI_PopMenu();
break;
case ID_OK:
case ID_APPLY:
UI_VidOptions_SetConfig ();
break;
}
@ -189,6 +187,8 @@ static void UI_VidModes_Init( void )
{
memset( &uiVidModes, 0, sizeof( uiVidModes_t ));
uiVidModes.menu.vidInitFunc = UI_VidModes_Init;
strcat( uiVidModes.hintText, "Change Xash3D rendering engine\n" );
strcat( uiVidModes.hintText, "to get more compatibility and\n" );
strcat( uiVidModes.hintText, "optimize FPS.\n" );
@ -213,21 +213,21 @@ static void UI_VidModes_Init( void )
uiVidModes.banner.generic.height = UI_BANNER_HEIGHT;
uiVidModes.banner.pic = ART_BANNER;
uiVidModes.ok.generic.id = ID_OK;
uiVidModes.ok.generic.id = ID_APPLY;
uiVidModes.ok.generic.type = QMTYPE_ACTION;
uiVidModes.ok.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiVidModes.ok.generic.x = 72;
uiVidModes.ok.generic.y = 230;
uiVidModes.ok.generic.name = "Ok";
uiVidModes.ok.generic.statusText = "Apply changes and return to the Main Menu";
uiVidModes.ok.generic.name = "Apply";
uiVidModes.ok.generic.statusText = "Apply changes";
uiVidModes.ok.generic.callback = UI_VidModes_Callback;
uiVidModes.cancel.generic.id = ID_CANCEL;
uiVidModes.cancel.generic.id = ID_DONE;
uiVidModes.cancel.generic.type = QMTYPE_ACTION;
uiVidModes.cancel.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
uiVidModes.cancel.generic.x = 72;
uiVidModes.cancel.generic.y = 280;
uiVidModes.cancel.generic.name = "Cancel";
uiVidModes.cancel.generic.name = "Done";
uiVidModes.cancel.generic.statusText = "Return back to previous menu";
uiVidModes.cancel.generic.callback = UI_VidModes_Callback;

View File

@ -142,6 +142,8 @@ static void UI_VidOptions_Init( void )
{
memset( &uiVidOptions, 0, sizeof( uiVidOptions_t ));
uiVidOptions.menu.vidInitFunc = UI_VidOptions_Init;
uiVidOptions.background.generic.id = ID_BACKGROUND;
uiVidOptions.background.generic.type = QMTYPE_BITMAP;
uiVidOptions.background.generic.flags = QMF_INACTIVE;

View File

@ -122,8 +122,8 @@ typedef enum
CVAR_LATCH = BIT(14),// save changes until server restart
CVAR_READ_ONLY = BIT(15),// display only, cannot be set by user at all
CVAR_LATCH_VIDEO = BIT(16),// save changes until render restart
CVAR_LATCH_AUDIO = BIT(17),// save changes until vsound restart
CVAR_USER_CREATED = BIT(18),// created by a set command (dll's used)
CVAR_USER_CREATED = BIT(17),// created by a set command (dll's used)
CVAR_GLCONFIG = BIT(18),// set to cause it to be saved to opengl.cfg
} cvar_flags_t;
#include "cvardef.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,456 +0,0 @@
/*
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.
*/
#ifndef __R_BACKEND_H__
#define __R_BACKEND_H__
#define MAX_LIGHTMAPS 128
#define MAX_SUPER_STYLES 1024 // unique lightstyle combiantions
#define MAX_TEXTURES 4096
#define MAX_ARRAY_VERTS 12288
#define MAX_ARRAY_ELEMENTS MAX_ARRAY_VERTS * 6
#define MAX_ARRAY_TRIANGLES MAX_ARRAY_ELEMENTS / 3
#define MAX_ARRAY_NEIGHBORS MAX_ARRAY_TRIANGLES * 3
enum
{
VBO_VERTS,
VBO_NORMALS,
VBO_COLORS,
VBO_TC0,
VBO_ENDMARKER
};
#define MAX_SHADOWGROUPS 32
#define MAX_VERTEX_BUFFER_OBJECTS VBO_ENDMARKER+MAX_TEXTURE_UNITS-1
extern ALIGN( 16 ) vec4_t inVertsArray[MAX_ARRAY_VERTS];
extern ALIGN( 16 ) vec4_t inNormalsArray[MAX_ARRAY_VERTS];
extern vec4_t inSVectorsArray[MAX_ARRAY_VERTS];
extern vec4_t inTVectorsArray[MAX_ARRAY_VERTS];
extern elem_t inElemsArray[MAX_ARRAY_ELEMENTS];
extern vec2_t inCoordsArray[MAX_ARRAY_VERTS];
extern vec2_t inLightmapCoordsArray[MAX_ARRAY_VERTS];
extern rgba_t inColorsArray[MAX_ARRAY_VERTS];
extern elem_t *elemsArray;
extern vec4_t *vertsArray;
extern vec4_t *normalsArray;
extern vec4_t *sVectorsArray;
extern vec4_t *tVectorsArray;
extern vec2_t *coordsArray;
extern vec2_t *lightmapCoordsArray;
extern rgba_t colorArray[MAX_ARRAY_VERTS];
extern int r_features;
//===================================================================
typedef struct vbo_buffer_s
{
byte *pointer;
int size;
uint usage;
uint bufNum;
} vbo_buffer_t;
typedef struct
{
int features;
int lightmapNum;
float stOffset[2];
int lightmapStyles[LM_STYLES];
} ref_style_t;
typedef struct
{
uint numVerts;
uint numElems;
uint numColors;
uint c_totalVerts;
uint c_totalTris;
uint c_totalFlushes;
uint c_totalKeptLocks;
} ref_backacc_t;
typedef struct
{
// renderer global variables
int registration_sequence;
int iRenderMode;
// vbo stuff
int numVertexBufferObjects;
vbo_buffer_t vertexBufferObjects[MAX_VERTEX_BUFFER_OBJECTS];
vbo_buffer_t *vertexBuffer;
vbo_buffer_t *normalBuffer;
vbo_buffer_t *colorsBuffer;
vbo_buffer_t *tcoordBuffer[MAX_TEXTURE_UNITS];
// OpenGL matrix states
qboolean modelviewIdentity;
// super lightstyles
ref_style_t superLightStyles[MAX_SUPER_STYLES];
int numSuperLightStyles;
// builtin textures
texture_t *cinTexture; // cinematic texture
texture_t *portaltexture1; // portal view
texture_t *portaltexture2; // refraction image for distortions
texture_t *defaultTexture; // use for bad textures
texture_t *particleTexture; // little dot for particles
texture_t *whiteTexture;
texture_t *blackTexture;
texture_t *blankbumpTexture;
texture_t *dlightTexture;
texture_t *dspotlightTexture;
texture_t *normalizeTexture; // cubemap
texture_t *fogTexture;
texture_t *skyTexture;
texture_t *coronaTexture;
texture_t *shadowmapTextures[MAX_SHADOWGROUPS];
texture_t *lightmapTextures[MAX_LIGHTMAPS];
// utility shaders
ref_shader_t *defaultShader; // generic black texture
ref_shader_t *fillShader; // generic white texture
ref_shader_t *currentSkyShader; // ponter to sky shader for current map
} ref_globals_t;
extern ref_globals_t tr;
extern ref_backacc_t r_backacc;
//===================================================================
void R_BackendInit( void );
void R_BackendShutdown( void );
void R_BackendStartFrame( void );
void R_BackendEndFrame( void );
void R_BackendResetCounters( void );
void R_BackendBeginTriangleOutlines( void );
void R_BackendEndTriangleOutlines( void );
void R_BackendCleanUpTextureUnits( void );
void R_BackendSetPassMask( int mask );
void R_BackendResetPassMask( void );
void R_DrawEntitiesDebug( void );
void R_DrawPhysDebug( void );
void R_InitVertexBuffers( void );
void R_ShutdownVertexBuffers( void );
vbo_buffer_t *R_AllocVertexBuffer( size_t size, GLuint usage );
void R_UpdateVertexBuffer( vbo_buffer_t *vertexBuffer, const void *data, size_t size );
void R_LockArrays( int numverts );
void R_UnlockArrays( void );
void R_UnlockArrays( void );
void R_FlushArrays( void );
void R_FlushArraysMtex( void );
void R_ClearArrays( void );
static _inline void R_PushElems( elem_t *elems, int count, int features )
{
elem_t *currentElem;
// this is a fast path for non-batched geometry, use carefully
// used on pics, sprites, .dpm, .md3 and .md2 models
if( features & MF_NONBATCHED )
{
// simply change elemsArray to point at elems
r_backacc.numElems = count;
elemsArray = currentElem = elems;
}
else
{
currentElem = elemsArray + r_backacc.numElems;
r_backacc.numElems += count;
// the following code assumes that R_PushElems is fed with triangles...
for(; count > 0; count -= 3, elems += 3, currentElem += 3 )
{
currentElem[0] = r_backacc.numVerts + elems[0];
currentElem[1] = r_backacc.numVerts + elems[1];
currentElem[2] = r_backacc.numVerts + elems[2];
}
}
}
static _inline void R_PushTrifanElems( int numverts )
{
elem_t *currentElem;
int count;
currentElem = elemsArray + r_backacc.numElems;
r_backacc.numElems += numverts + numverts + numverts - 6;
for( count = 2; count < numverts; count++, currentElem += 3 )
{
currentElem[0] = r_backacc.numVerts;
currentElem[1] = r_backacc.numVerts + count - 1;
currentElem[2] = r_backacc.numVerts + count;
}
}
static _inline void R_PushMesh( const mesh_t *mesh, int features )
{
int numverts;
if( !mesh || !( mesh->elems || ( features & MF_TRIFAN )) || !mesh->vertexArray )
return;
r_features = features;
if( features & MF_TRIFAN ) R_PushTrifanElems( mesh->numVerts );
else R_PushElems( mesh->elems, mesh->numElems, features );
numverts = mesh->numVerts;
if( features & MF_NONBATCHED )
{
if( features & MF_DEFORMVS )
{
if( mesh->vertexArray != inVertsArray )
Mem_Copy( inVertsArray, mesh->vertexArray, numverts * sizeof( vec4_t ) );
if( ( features & MF_NORMALS ) && mesh->normalsArray && ( mesh->normalsArray != inNormalsArray ) )
Mem_Copy( inNormalsArray, mesh->normalsArray, numverts * sizeof( vec4_t ) );
}
else
{
vertsArray = mesh->vertexArray;
if( ( features & MF_NORMALS ) && mesh->normalsArray )
normalsArray = mesh->normalsArray;
}
if(( features & MF_STCOORDS ) && mesh->stCoordArray )
coordsArray = mesh->stCoordArray;
if(( features & MF_LMCOORDS ) && mesh->lmCoordArray )
lightmapCoordsArray = mesh->lmCoordArray;
if(( features & MF_SVECTORS ) && mesh->sVectorsArray )
sVectorsArray = mesh->sVectorsArray;
if(( features & MF_TVECTORS ) && mesh->tVectorsArray )
tVectorsArray = mesh->tVectorsArray;
}
else
{
if( mesh->vertexArray != inVertsArray )
Mem_Copy( inVertsArray[r_backacc.numVerts], mesh->vertexArray, numverts * sizeof( vec4_t ));
if(( features & MF_NORMALS ) && mesh->normalsArray && (mesh->normalsArray != inNormalsArray ))
Mem_Copy( inNormalsArray[r_backacc.numVerts], mesh->normalsArray, numverts * sizeof( vec4_t ));
if(( features & MF_STCOORDS ) && mesh->stCoordArray && ( mesh->stCoordArray != inCoordsArray ))
Mem_Copy( inCoordsArray[r_backacc.numVerts], mesh->stCoordArray, numverts * sizeof( vec2_t ));
if(( features & MF_LMCOORDS ) && mesh->lmCoordArray && ( mesh->lmCoordArray != inLightmapCoordsArray ))
Mem_Copy( inLightmapCoordsArray[r_backacc.numVerts], mesh->lmCoordArray, numverts * sizeof( vec2_t ));
if(( features & MF_SVECTORS ) && mesh->sVectorsArray && (mesh->sVectorsArray != inSVectorsArray ))
Mem_Copy( inSVectorsArray[r_backacc.numVerts], mesh->sVectorsArray, numverts * sizeof( vec4_t ));
if(( features & MF_TVECTORS ) && mesh->tVectorsArray && (mesh->tVectorsArray != inTVectorsArray ))
Mem_Copy( inTVectorsArray[r_backacc.numVerts], mesh->tVectorsArray, numverts * sizeof( vec4_t ));
}
if(( features & MF_COLORS ) && mesh->colorsArray )
Mem_Copy( inColorsArray[r_backacc.numVerts], mesh->colorsArray, numverts * sizeof( rgba_t ));
r_backacc.numVerts += numverts;
r_backacc.c_totalVerts += numverts;
}
static _inline qboolean R_MeshOverflow( const mesh_t *mesh )
{
if( !mesh ) return false;
return ( r_backacc.numVerts + mesh->numVerts > MAX_ARRAY_VERTS || r_backacc.numElems + mesh->numElems > MAX_ARRAY_ELEMENTS );
}
static _inline qboolean R_MeshOverflow2( const mesh_t *mesh1, const mesh_t *mesh2 )
{
return ( r_backacc.numVerts + mesh1->numVerts + mesh2->numVerts > MAX_ARRAY_VERTS ||
r_backacc.numElems + mesh1->numElems + mesh2->numElems > MAX_ARRAY_ELEMENTS );
}
static _inline qboolean R_InvalidMesh( const mesh_t *mesh )
{
return ( !mesh->numVerts || !mesh->numElems || mesh->numVerts > MAX_ARRAY_VERTS || mesh->numElems > MAX_ARRAY_ELEMENTS );
}
void R_RenderMeshBuffer( const meshbuffer_t *mb );
/*
=======================================================================
GL STATE MACHINE
=======================================================================
*/
// render supported extensions
// this part are shared with engine.dll
#define R_OPENGL_110 0 // base
#define R_WGL_SWAPCONTROL 1
#define R_HARDWARE_GAMMA_CONTROL 2
#define R_ARB_VERTEX_BUFFER_OBJECT_EXT 3
#define R_ENV_COMBINE_EXT 4
#define R_ARB_MULTITEXTURE 5
#define R_TEXTURECUBEMAP_EXT 6
#define R_DOT3_ARB_EXT 7
#define R_ANISOTROPY_EXT 8
#define R_TEXTURE_LODBIAS 9
#define R_OCCLUSION_QUERIES_EXT 10
#define R_TEXTURE_COMPRESSION_EXT 11
#define R_SHADER_GLSL100_EXT 12
// this part are private for render.dll
#define R_WGL_3DFX_GAMMA_CONTROL 13
#define R_SGIS_MIPMAPS_EXT 14
#define R_DRAW_RANGEELEMENTS_EXT 15
#define R_LOCKARRAYS_EXT 16
#define R_TEXTURE_3D_EXT 17
#define R_CLAMPTOEDGE_EXT 18
#define R_BLEND_MINMAX_EXT 19
#define R_STENCILTWOSIDE_EXT 20
#define R_BLEND_SUBTRACT_EXT 21
#define R_SHADER_OBJECTS_EXT 22
#define R_VERTEX_SHADER_EXT 23 // glsl vertex program
#define R_FRAGMENT_SHADER_EXT 24 // glsl fragment program
#define R_EXT_POINTPARAMETERS 25
#define R_SEPARATESTENCIL_EXT 26
#define R_ARB_TEXTURE_NPOT_EXT 27
#define R_CUSTOM_VERTEX_ARRAY_EXT 28
#define R_TEXTURE_ENV_ADD_EXT 29
#define R_CLAMP_TEXBORDER_EXT 30
#define R_DEPTH_TEXTURE 31
#define R_SHADOW_EXT 32
#define R_GLSL_NO_HALF_TYPES 33 // fake extension
#define R_GLSL_BRANCHING 34 // fake extension
#define R_EXTCOUNT 35
typedef struct
{
const char *renderer_string; // ptrs to OpenGL32.dll, use with caution
const char *vendor_string;
const char *version_string;
// list of supported extensions
const char *extensions_string;
byte extension[R_EXTCOUNT];
int max_texture_units;
GLint max_2d_texture_size;
GLint max_2d_rectangle_size;
GLint max_3d_texture_size;
GLint max_cubemap_texture_size;
GLint texRectangle;
GLfloat max_texture_anisotropy;
GLfloat max_texture_lodbias;
int color_bits;
int depth_bits;
int stencil_bits;
qboolean allowCDS;
qboolean deviceSupportsGamma;
int prev_mode;
} glconfig_t;
typedef struct
{
int flags;
word gammaRamp[768]; // current gamma ramp
word stateRamp[768]; // original gamma ramp
int width, height;
qboolean fullScreen;
qboolean wideScreen;
qboolean initializedMedia;
int activeTMU;
GLuint currentTextures[MAX_TEXTURE_UNITS];
GLenum currentEnvModes[MAX_TEXTURE_UNITS];
GLqbooleanean 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
rgba_t draw_color;
int draw_rendermode; // rendermode for drawing
int draw_frame; // will be reset after each drawing
int faceCull;
int frontFace;
qboolean stencilEnabled;
qboolean in2DMode;
} glstate_t;
typedef struct
{
qboolean fActive; // drawing in progress
int currentRenderMode;
shader_t currentShader;
int vertexState;
int drawMode;
rgba_t color;
vec3_t lightingOrigin;
vec3_t mins, maxs; // for compute lightbounds
// linear fog stuff
vec4_t fogColor;
float fogStartDist;
float fogEndDist;
qboolean fogEnabled;
int features;
int numVertex;
int numColor;
int numIndex;
qboolean noCulling;
qboolean checkFlush;
qboolean hasNormals;
} tristate_t;
extern glconfig_t glConfig;
extern glstate_t glState;
extern tristate_t triState;
// r_register.c
void GL_InitBackend( void );
qboolean GL_Support( int r_ext );
void GL_InitExtensions( void );
void GL_ShutdownBackend( void );
void GL_UpdateSwapInterval( void );
void GL_UpdateGammaRamp( void );
void GL_SetExtension( int r_ext, int enable );
void GL_BuildGammaTable( void );
qboolean R_Init_OpenGL( void );
void R_Free_OpenGL( void );
#endif /*__R_BACKEND_H__*/

View File

@ -1,524 +0,0 @@
/*
Copyright (C) Forest Hale
Copyright (C) 2006-2007 German Garcia
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.
*/
// r_bloom.c: 2D lighting post process effect
#include "r_local.h"
/*
==============================================================================
LIGHT BLOOMS
==============================================================================
*/
static float Diamond8x[8][8] =
{
{ 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f, },
{ 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, },
{ 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, },
{ 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, },
{ 0.1f, 0.3f, 0.6f, 0.9f, 0.9f, 0.6f, 0.3f, 0.1f, },
{ 0.0f, 0.2f, 0.4f, 0.6f, 0.6f, 0.4f, 0.2f, 0.0f, },
{ 0.0f, 0.0f, 0.2f, 0.3f, 0.3f, 0.2f, 0.0f, 0.0f, },
{ 0.0f, 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, 0.0f }
};
static float Diamond6x[6][6] =
{
{ 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f, },
{ 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, },
{ 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, },
{ 0.1f, 0.5f, 0.9f, 0.9f, 0.5f, 0.1f, },
{ 0.0f, 0.3f, 0.5f, 0.5f, 0.3f, 0.0f, },
{ 0.0f, 0.0f, 0.1f, 0.1f, 0.0f, 0.0f }
};
static float Diamond4x[4][4] =
{
{ 0.3f, 0.4f, 0.4f, 0.3f, },
{ 0.4f, 0.9f, 0.9f, 0.4f, },
{ 0.4f, 0.9f, 0.9f, 0.4f, },
{ 0.3f, 0.4f, 0.4f, 0.3f }
};
static int BLOOM_SIZE;
static texture_t *r_bloomscreentexture;
static texture_t *r_bloomeffecttexture;
static texture_t *r_bloombackuptexture;
static texture_t *r_bloomdownsamplingtexture;
static int r_screendownsamplingtexture_size;
static int screen_texture_width, screen_texture_height;
static int r_screenbackuptexture_width, r_screenbackuptexture_height;
// current refdef size:
static int curView_x;
static int curView_y;
static int curView_width;
static int curView_height;
// texture coordinates of screen data inside screentexture
static float screenTex_tcw;
static float screenTex_tch;
static int sample_width;
static int sample_height;
// texture coordinates of adjusted textures
static float sampleText_tcw;
static float sampleText_tch;
/*
=================
R_Bloom_InitBackUpTexture
=================
*/
static void R_Bloom_InitBackUpTexture( int width, int height )
{
rgbdata_t r_bloom;
Mem_Set( &r_bloom, 0, sizeof( rgbdata_t ));
r_screenbackuptexture_width = width;
r_screenbackuptexture_height = height;
r_bloom.width = width;
r_bloom.height = height;
r_bloom.type = PF_RGBA_32;
r_bloom.size = width * height * 4;
r_bloom.flags = 0;
r_bloom.palette = NULL;
r_bloom.buffer = Mem_Alloc( r_temppool, width * height * 4 );
r_bloombackuptexture = R_LoadTexture( "***r_bloombackuptexture***", &r_bloom, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP );
Mem_Free( r_bloom.buffer );
}
/*
=================
R_Bloom_InitEffectTexture
=================
*/
static void R_Bloom_InitEffectTexture( void )
{
int limit;
rgbdata_t r_bloomfx;
Mem_Set( &r_bloomfx, 0, sizeof( rgbdata_t ));
if( r_bloom_sample_size->integer < 32 )
Cvar_Set( "r_bloom_sample_size", "32" );
// make sure bloom size doesn't have stupid values
limit = min( r_bloom_sample_size->integer, min( screen_texture_width, screen_texture_height ) );
if( GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
BLOOM_SIZE = limit;
else // make sure bloom size is a power of 2
for( BLOOM_SIZE = 32; (BLOOM_SIZE<<1) <= limit; BLOOM_SIZE <<= 1 );
if( BLOOM_SIZE != r_bloom_sample_size->integer )
Cvar_Set( "r_bloom_sample_size", va( "%i", BLOOM_SIZE ) );
r_bloomfx.width = BLOOM_SIZE;
r_bloomfx.height = BLOOM_SIZE;
r_bloomfx.size = BLOOM_SIZE * BLOOM_SIZE * 4;
r_bloomfx.type = PF_RGBA_32;
r_bloomfx.flags = 0;
r_bloomfx.palette = NULL;
r_bloomfx.buffer = Mem_Alloc( r_temppool, BLOOM_SIZE * BLOOM_SIZE * 4 );
r_bloomeffecttexture = R_LoadTexture( "***r_bloomeffecttexture***", &r_bloomfx, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP );
Mem_Free( r_bloomfx.buffer );
}
/*
=================
R_Bloom_InitTextures
=================
*/
static void R_Bloom_InitTextures( void )
{
int size;
rgbdata_t r_bloomscr, r_downsample;
Mem_Set( &r_bloomscr, 0, sizeof( rgbdata_t ));
Mem_Set( &r_downsample, 0, sizeof( rgbdata_t ));
if( GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
{
screen_texture_width = glState.width;
screen_texture_height = glState.height;
}
else
{
// find closer power of 2 to screen size
for (screen_texture_width = 1;screen_texture_width < glState.width;screen_texture_width <<= 1);
for (screen_texture_height = 1;screen_texture_height < glState.height;screen_texture_height <<= 1);
}
// disable blooms if we can't handle a texture of that size
if( screen_texture_width > glConfig.max_2d_texture_size || screen_texture_height > glConfig.max_2d_texture_size )
{
screen_texture_width = screen_texture_height = 0;
Cvar_Set( "r_bloom_intensity", "0" );
MsgDev( D_WARN, "'R_InitBloomScreenTexture' too high resolution for light bloom, effect disabled\n" );
return;
}
// init the screen texture
size = screen_texture_width * screen_texture_height * 4;
r_bloomscr.width = screen_texture_width;
r_bloomscr.height = screen_texture_height;
r_bloomscr.type = PF_RGBA_32;
r_bloomscr.flags = 0;
r_bloomscr.palette = NULL;
r_bloomscr.size = size;
r_bloomscr.buffer = Mem_Alloc( r_temppool, size );
Mem_Set( r_bloomscr.buffer, 255, size );
r_bloomscreentexture = R_LoadTexture( "***r_bloomscreentexture***", &r_bloomscr, 3, TF_STATIC|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_NOMIPMAP );
Mem_Free( r_bloomscr.buffer );
// validate bloom size and init the bloom effect texture
R_Bloom_InitEffectTexture();
// if screensize is more than 2x the bloom effect texture, set up for stepped downsampling
r_bloomdownsamplingtexture = NULL;
r_screendownsamplingtexture_size = 0;
if(( glState.width > (BLOOM_SIZE * 2) || glState.height > (BLOOM_SIZE * 2)) && !r_bloom_fast_sample->integer )
{
r_screendownsamplingtexture_size = (int)( BLOOM_SIZE * 2 );
r_downsample.width = r_screendownsamplingtexture_size;
r_downsample.height = r_screendownsamplingtexture_size;
r_downsample.type = PF_RGBA_32;
r_downsample.size = r_screendownsamplingtexture_size * r_screendownsamplingtexture_size * 4;
r_downsample.flags = 0;
r_downsample.palette = NULL;
r_downsample.buffer = Mem_Alloc( r_temppool, r_downsample.size );
r_bloomdownsamplingtexture = R_LoadTexture( "***r_bloomdownsamplingtexture***", &r_downsample, 3, TF_STATIC|TF_NOPICMIP|TF_UNCOMPRESSED|TF_CLAMP|TF_NOMIPMAP );
Mem_Free( r_downsample.buffer );
}
// init the screen backup texture
if( r_screendownsamplingtexture_size )
R_Bloom_InitBackUpTexture( r_screendownsamplingtexture_size, r_screendownsamplingtexture_size );
else R_Bloom_InitBackUpTexture( BLOOM_SIZE, BLOOM_SIZE );
}
/*
=================
R_InitBloomTextures
=================
*/
void R_InitBloomTextures( void )
{
BLOOM_SIZE = 0;
if( !r_bloom_intensity->integer )
return;
R_Bloom_InitTextures();
}
/*
=================
R_Bloom_SamplePass
=================
*/
static _inline void R_Bloom_SamplePass( int xpos, int ypos )
{
pglBegin( GL_QUADS );
pglTexCoord2f( 0, sampleText_tch );
pglVertex2f( xpos, ypos );
pglTexCoord2f( 0, 0 );
pglVertex2f( xpos, ypos+sample_height );
pglTexCoord2f( sampleText_tcw, 0 );
pglVertex2f( xpos+sample_width, ypos+sample_height );
pglTexCoord2f( sampleText_tcw, sampleText_tch );
pglVertex2f( xpos+sample_width, ypos );
pglEnd();
}
/*
=================
R_Bloom_Quad
=================
*/
static _inline void R_Bloom_Quad( int x, int y, int w, int h, float texwidth, float texheight )
{
pglBegin( GL_QUADS );
pglTexCoord2f( 0, texheight );
pglVertex2f( x, glState.height-h-y );
pglTexCoord2f( 0, 0 );
pglVertex2f( x, glState.height-y );
pglTexCoord2f( texwidth, 0 );
pglVertex2f( x+w, glState.height-y );
pglTexCoord2f( texwidth, texheight );
pglVertex2f( x+w, glState.height-h );
pglEnd();
}
/*
=================
R_Bloom_DrawEffect
=================
*/
static void R_Bloom_DrawEffect( void )
{
GL_Bind( 0, r_bloomeffecttexture );
GL_TexEnv( GL_MODULATE );
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE );
pglColor4f( r_bloom_alpha->value, r_bloom_alpha->value, r_bloom_alpha->value, 1.0f );
pglBegin( GL_QUADS );
pglTexCoord2f( 0, sampleText_tch );
pglVertex2f( curView_x, curView_y );
pglTexCoord2f( 0, 0 );
pglVertex2f( curView_x, curView_y+curView_height );
pglTexCoord2f( sampleText_tcw, 0 );
pglVertex2f( curView_x+curView_width, curView_y+curView_height );
pglTexCoord2f( sampleText_tcw, sampleText_tch );
pglVertex2f( curView_x+curView_width, curView_y );
pglEnd();
}
/*
=================
R_Bloom_GeneratexDiamonds
=================
*/
static void R_Bloom_GeneratexDiamonds( void )
{
int i, j, k;
float intensity, scale, *diamond;
// set up sample size workspace
pglScissor( 0, 0, sample_width, sample_height );
pglViewport( 0, 0, sample_width, sample_height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, sample_width, sample_height, 0, -10, 100 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
// copy small scene into r_bloomeffecttexture
GL_Bind( 0, r_bloomeffecttexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );
// start modifying the small scene corner
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
// darkening passes
if( r_bloom_darken->integer )
{
GL_TexEnv( GL_MODULATE );
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_DST_COLOR|GLSTATE_DSTBLEND_ZERO );
for( i = 0; i < r_bloom_darken->integer; i++ )
R_Bloom_SamplePass( 0, 0 );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );
}
// bluring passes
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR );
if( r_bloom_diamond_size->integer > 7 || r_bloom_diamond_size->integer <= 3 )
{
if( r_bloom_diamond_size->integer != 8 )
Cvar_Set( "r_bloom_diamond_size", "8" );
}
else if( r_bloom_diamond_size->integer > 5 )
{
if( r_bloom_diamond_size->integer != 6 )
Cvar_Set( "r_bloom_diamond_size", "6" );
}
else if( r_bloom_diamond_size->integer > 3 )
{
if( r_bloom_diamond_size->integer != 4 )
Cvar_Set( "r_bloom_diamond_size", "4" );
}
switch( r_bloom_diamond_size->integer )
{
case 4:
k = 2;
diamond = &Diamond4x[0][0];
scale = r_bloom_intensity->value * 0.8f;
break;
case 6:
k = 3;
diamond = &Diamond6x[0][0];
scale = r_bloom_intensity->value * 0.5f;
break;
default:
k = 4;
diamond = &Diamond8x[0][0];
scale = r_bloom_intensity->value * 0.3f;
break;
}
for( i = 0; i < r_bloom_diamond_size->integer; i++ )
{
for( j = 0; j < r_bloom_diamond_size->integer; j++, diamond++ )
{
intensity = *diamond * scale;
if( intensity < 0.01f )
continue;
pglColor4f( intensity, intensity, intensity, 1.0 );
R_Bloom_SamplePass( i - k, j - k );
}
}
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, sample_width, sample_height );
// restore full screen workspace
pglScissor( 0, 0, glState.width, glState.height );
pglViewport( 0, 0, glState.width, glState.height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, glState.width, glState.height, 0, -10, 100 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
}
/*
=================
R_Bloom_DownsampleView
=================
*/
static void R_Bloom_DownsampleView( void )
{
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
if( r_screendownsamplingtexture_size )
{
// stepped downsample
int midsample_width = ( r_screendownsamplingtexture_size * sampleText_tcw );
int midsample_height = ( r_screendownsamplingtexture_size * sampleText_tch );
// copy the screen and draw resized
GL_Bind( 0, r_bloomscreentexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height );
R_Bloom_Quad( 0, 0, midsample_width, midsample_height, screenTex_tcw, screenTex_tch );
// now copy into downsampling (mid-sized) texture
GL_Bind( 0, r_bloomdownsamplingtexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, midsample_width, midsample_height );
// now draw again in bloom size
pglColor4f( 0.5f, 0.5f, 0.5f, 1.0f );
R_Bloom_Quad( 0, 0, sample_width, sample_height, sampleText_tcw, sampleText_tch );
// now blend the big screen texture into the bloom generation space (hoping it adds some blur)
GL_SetState( GLSTATE_NO_DEPTH_TEST|GLSTATE_SRCBLEND_ONE|GLSTATE_DSTBLEND_ONE );
GL_Bind( 0, r_bloomscreentexture );
R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch );
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f );
}
else
{
// downsample simple
GL_Bind( 0, r_bloomscreentexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, curView_x, glState.height - ( curView_y + curView_height ), curView_width, curView_height );
R_Bloom_Quad( 0, 0, sample_width, sample_height, screenTex_tcw, screenTex_tch );
}
}
/*
=================
R_BloomBlend
=================
*/
void R_BloomBlend( const ref_params_t *fd )
{
if( !r_bloom_intensity->integer )
return;
if( !BLOOM_SIZE )
R_Bloom_InitTextures();
if( screen_texture_width < BLOOM_SIZE || screen_texture_height < BLOOM_SIZE )
return;
// set up full screen workspace
pglScissor( 0, 0, glState.width, glState.height );
pglViewport( 0, 0, glState.width, glState.height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, glState.width, glState.height, 0, -10, 100 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
GL_Cull( 0 );
GL_SetState( GLSTATE_NO_DEPTH_TEST );
pglColor4f( 1, 1, 1, 1 );
// set up current sizes
curView_x = fd->viewport[0];
curView_y = fd->viewport[1];
curView_width = fd->viewport[2];
curView_height = fd->viewport[3];
screenTex_tcw = ( (float)curView_width / (float)screen_texture_width );
screenTex_tch = ( (float)curView_height / (float)screen_texture_height );
if( curView_height > curView_width )
{
sampleText_tcw = ( (float)curView_width / (float)curView_height );
sampleText_tch = 1.0f;
}
else
{
sampleText_tcw = 1.0f;
sampleText_tch = ( (float)curView_height / (float)curView_width );
}
sample_width = ( BLOOM_SIZE * sampleText_tcw );
sample_height = ( BLOOM_SIZE * sampleText_tch );
// copy the screen space we'll use to work into the backup texture
GL_Bind( 0, r_bloombackuptexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height );
// create the bloom image
R_Bloom_DownsampleView();
R_Bloom_GeneratexDiamonds();
// restore the screen-backup to the screen
GL_SetState( GLSTATE_NO_DEPTH_TEST );
GL_Bind( 0, r_bloombackuptexture );
pglColor4f( 1, 1, 1, 1 );
R_Bloom_Quad( 0, 0, r_screenbackuptexture_width, r_screenbackuptexture_height, 1.0f, 1.0f );
pglScissor( RI.scissor[0], RI.scissor[1], RI.scissor[2], RI.scissor[3] );
R_Bloom_DrawEffect();
pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] );
}

View File

@ -1,585 +0,0 @@
/*
Copyright (C) 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 "cl_entity.h"
/*
=============================================================
FRUSTUM AND PVS CULLING
=============================================================
*/
/*
=================
R_CullBox
Returns true if the box is completely outside the frustum
=================
*/
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, const uint clipflags )
{
uint i, bit;
const mplane_t *p;
if( r_nocull->integer )
return false;
for( i = sizeof( RI.frustum )/sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit<<=1, p++ )
{
if( !( clipflags & bit ))
continue;
switch( p->signbits )
{
case 0:
if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist )
return true;
break;
case 1:
if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist )
return true;
break;
case 2:
if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist )
return true;
break;
case 3:
if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist )
return true;
break;
case 4:
if( p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist )
return true;
break;
case 5:
if( p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist )
return true;
break;
case 6:
if( p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist )
return true;
break;
case 7:
if( p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist )
return true;
break;
default:
return false;
}
}
return false;
}
/*
=================
R_CullSphere
Returns true if the sphere is completely outside the frustum
=================
*/
qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags )
{
uint i, bit;
const mplane_t *p;
if( r_nocull->integer )
return false;
for( i = sizeof( RI.frustum ) / sizeof( RI.frustum[0] ), bit = 1, p = RI.frustum; i > 0; i--, bit <<= 1, p++ )
{
if(!( clipflags & bit )) continue;
if( DotProduct( centre, p->normal ) - p->dist <= -radius )
return true;
}
return false;
}
/*
===================
R_VisCullBox
===================
*/
qboolean R_VisCullBox( const vec3_t mins, const vec3_t maxs )
{
int s, stackdepth = 0;
vec3_t extmins, extmaxs;
mnode_t *node, *localstack[2048];
if( !r_worldmodel || ( RI.drawWorld == false ))
return false;
if( r_novis->integer )
return false;
for( s = 0; s < 3; s++ )
{
extmins[s] = mins[s] - 4;
extmaxs[s] = maxs[s] + 4;
}
for( node = r_worldbrushmodel->nodes; node; )
{
if( node->pvsframe != r_pvsframecount )
{
if( !stackdepth )
return true;
node = localstack[--stackdepth];
continue;
}
if( !node->plane )
return false;
s = BOX_ON_PLANE_SIDE( extmins, extmaxs, node->plane ) - 1;
if( s < 2 )
{
node = node->children[s];
continue;
}
// go down both sides
if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ) )
localstack[stackdepth++] = node->children[0];
node = node->children[1];
}
return true;
}
/*
===================
R_VisCullSphere
===================
*/
qboolean R_VisCullSphere( const vec3_t origin, float radius )
{
float dist;
int stackdepth = 0;
mnode_t *node, *localstack[2048];
if( !r_worldmodel || ( RI.drawWorld == false ))
return false;
if( r_novis->integer )
return false;
radius += 4;
for( node = r_worldbrushmodel->nodes;; )
{
if( node->pvsframe != r_pvsframecount )
{
if( !stackdepth )
return true;
node = localstack[--stackdepth];
continue;
}
if( !node->plane )
return false;
dist = PlaneDiff( origin, node->plane );
if( dist > radius )
{
node = node->children[0];
continue;
}
else if( dist < -radius )
{
node = node->children[1];
continue;
}
// go down both sides
if( stackdepth < sizeof( localstack )/sizeof( mnode_t * ) )
localstack[stackdepth++] = node->children[0];
node = node->children[1];
}
return true;
}
/*
=============
R_CullModel
=============
*/
int R_CullModel( ref_entity_t *e, vec3_t mins, vec3_t maxs, float radius )
{
if( e->ent_type == ET_VIEWENTITY )
{
if( RI.params & RP_NONVIEWERREF )
return 1;
return 0;
}
// don't reflect this entity in mirrors
if( e->flags & EF_NOREFLECT && RI.params & RP_MIRRORVIEW )
return 1;
// draw only in mirrors
if( e->flags & EF_REFLECTONLY && !( RI.params & RP_MIRRORVIEW ))
return 1;
if( RP_LOCALCLIENT( e ) && !RI.thirdPerson )
{
if(!( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW )))
return 1;
}
if( RP_FOLLOWENTITY( e ) && RP_LOCALCLIENT( e->parent ) && !RI.thirdPerson )
{
if(!( RI.params & ( RP_MIRRORVIEW|RP_SHADOWMAPVIEW )))
return 1;
}
if( R_CullSphere( e->origin, radius, RI.clipFlags ))
return 1;
if( RI.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( RI.params & RP_SKYPORTALVIEW ))
{
if( R_VisCullSphere( e->origin, radius ))
return 2;
}
return 0;
}
/*
=============================================================
OCCLUSION QUERIES
=============================================================
*/
// occlusion queries for entities
#define BEGIN_OQ_ENTITIES 0
#define MAX_OQ_ENTITIES MAX_ENTITIES
#define END_OQ_ENTITIES ( BEGIN_OQ_ENTITIES+MAX_OQ_ENTITIES )
// occlusion queries for planar shadows
#define BEGIN_OQ_PLANARSHADOWS END_OQ_ENTITIES
#define MAX_OQ_PLANARSHADOWS MAX_ENTITIES
#define END_OQ_PLANARSHADOWS ( BEGIN_OQ_PLANARSHADOWS+MAX_OQ_PLANARSHADOWS )
// occlusion queries for shadowgroups
#define BEGIN_OQ_SHADOWGROUPS END_OQ_PLANARSHADOWS
#define MAX_OQ_SHADOWGROUPS MAX_SHADOWGROUPS
#define END_OQ_SHADOWGROUPS ( BEGIN_OQ_SHADOWGROUPS+MAX_OQ_SHADOWGROUPS )
// custom occlusion queries (portals, mirrors, etc)
#define BEGIN_OQ_CUSTOM END_OQ_SHADOWGROUPS
#define MAX_OQ_CUSTOM MAX_SURF_QUERIES
#define END_OQ_CUSTOM ( BEGIN_OQ_CUSTOM+MAX_OQ_CUSTOM )
#define MAX_OQ_TOTAL ( MAX_OQ_ENTITIES+MAX_OQ_PLANARSHADOWS+MAX_OQ_SHADOWGROUPS+MAX_OQ_CUSTOM )
static byte r_queriesBits[MAX_OQ_TOTAL/8];
static GLuint r_occlusionQueries[MAX_OQ_TOTAL];
static meshbuffer_t r_occluderMB;
static ref_shader_t *r_occlusionShader;
static qboolean r_occludersQueued;
static ref_entity_t *r_occlusionEntity;
static void R_RenderOccludingSurfaces( void );
/*
===============
R_InitOcclusionQueries
===============
*/
void R_InitOcclusionQueries( void )
{
meshbuffer_t *meshbuf = &r_occluderMB;
if( !r_occlusionShader )
r_occlusionShader = R_LoadShader( "***r_occlusion***", SHADER_OPAQUE_OCCLUDER, false, 0, SHADER_INVALID );
if( !GL_Support( R_OCCLUSION_QUERIES_EXT ))
return;
pglGenQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries );
meshbuf->sortkey = MB_ENTITY2NUM( r_worldent ) | MB_MODEL;
meshbuf->shaderkey = r_occlusionShader->sortkey;
}
/*
===============
R_BeginOcclusionPass
===============
*/
void R_BeginOcclusionPass( void )
{
ASSERT( OCCLUSION_QUERIES_ENABLED( RI ));
r_occludersQueued = false;
r_occlusionEntity = r_worldent;
memset( r_queriesBits, 0, sizeof( r_queriesBits ) );
R_LoadIdentity();
R_BackendResetPassMask();
R_ClearSurfOcclusionQueryKeys();
pglShadeModel( GL_FLAT );
pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
pglDisable( GL_TEXTURE_2D );
}
/*
===============
R_EndOcclusionPass
===============
*/
void R_EndOcclusionPass( void )
{
ASSERT( OCCLUSION_QUERIES_ENABLED( RI ));
R_RenderOccludingSurfaces();
R_SurfIssueOcclusionQueries();
R_BackendResetPassMask();
R_BackendResetCounters();
if( r_occlusion_queries_finish->integer )
pglFinish();
else
pglFlush();
pglShadeModel( GL_SMOOTH );
pglEnable( GL_TEXTURE_2D );
pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
}
/*
===============
R_RenderOccludingSurfaces
===============
*/
static void R_RenderOccludingSurfaces( void )
{
if( !r_occludersQueued )
return;
r_occludersQueued = false;
R_RotateForEntity( r_occlusionEntity );
R_BackendResetPassMask();
R_RenderMeshBuffer( &r_occluderMB );
}
/*
===============
R_OcclusionShader
===============
*/
ref_shader_t *R_OcclusionShader( void )
{
return r_occlusionShader;
}
/*
===============
R_AddOccludingSurface
===============
*/
void R_AddOccludingSurface( msurface_t *surf, ref_shader_t *shader )
{
int diff = shader->flags ^ r_occlusionShader->flags;
if( R_MeshOverflow( surf->mesh ) || ( diff & ( SHADER_CULL_FRONT|SHADER_CULL_BACK ) ) || r_occlusionEntity != RI.currententity )
{
R_RenderOccludingSurfaces();
r_occlusionShader->flags ^= diff;
r_occlusionEntity = RI.currententity;
}
r_occludersQueued = true;
R_PushMesh( surf->mesh, 0 );
}
/*
===============
R_GetOcclusionQueryNum
===============
*/
int R_GetOcclusionQueryNum( int type, int key )
{
switch( type )
{
case OQ_ENTITY:
return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_ENTITIES + ( key%MAX_OQ_ENTITIES ) : -1;
case OQ_PLANARSHADOW:
return ( r_occlusion_queries->integer & 1 ) ? BEGIN_OQ_PLANARSHADOWS + ( key%MAX_OQ_PLANARSHADOWS ) : -1;
case OQ_SHADOWGROUP:
return ( r_occlusion_queries->integer & 2 ) ? BEGIN_OQ_SHADOWGROUPS + ( key%MAX_OQ_SHADOWGROUPS ) : -1;
case OQ_CUSTOM:
return BEGIN_OQ_CUSTOM + ( key%MAX_OQ_CUSTOM );
}
return -1;
}
/*
===============
R_IssueOcclusionQuery
===============
*/
int R_IssueOcclusionQuery( int query, ref_entity_t *e, vec3_t mins, vec3_t maxs )
{
vec3_t bbox[8];
static vec4_t verts[8];
static mesh_t mesh;
static elem_t indices[] =
{
0, 1, 2, 1, 2, 3, // top
7, 5, 6, 5, 6, 4, // bottom
4, 0, 6, 0, 6, 2, // front
3, 7, 1, 7, 1, 5, // back
0, 1, 4, 1, 4, 5, // left
7, 6, 3, 6, 3, 2, // right
};
int i;
if( query < 0 ) return -1;
if( r_queriesBits[query>>3] & ( 1<<( query & 7 )))
return -1;
r_queriesBits[query>>3] |= ( 1<<( query & 7 ));
R_RenderOccludingSurfaces();
mesh.numVerts = 8;
mesh.vertexArray = verts;
mesh.numElems = 36;
mesh.elems = indices;
r_occlusionShader->flags &= ~( SHADER_CULL_BACK|SHADER_CULL_FRONT );
pglBeginQueryARB( GL_SAMPLES_PASSED_ARB, r_occlusionQueries[query] );
R_TransformEntityBBox( e, mins, maxs, bbox, false );
for( i = 0; i < 8; i++ )
Vector4Set( verts[i], bbox[i][0], bbox[i][1], bbox[i][2], 1.0f );
R_RotateForEntity( e );
R_BackendSetPassMask( GLSTATE_MASK & ~GLSTATE_DEPTHWRITE );
R_PushMesh( &mesh, MF_NONBATCHED|MF_NOCULL );
R_RenderMeshBuffer( &r_occluderMB );
pglEndQueryARB( GL_SAMPLES_PASSED_ARB );
return query;
}
/*
===============
R_OcclusionQueryIssued
===============
*/
qboolean R_OcclusionQueryIssued( int query )
{
ASSERT( query >= 0 && query < MAX_OQ_TOTAL );
return r_queriesBits[query>>3] & ( 1<<( query & 7 ));
}
/*
===============
R_GetOcclusionQueryResult
===============
*/
unsigned int R_GetOcclusionQueryResult( int query, qboolean wait )
{
GLint available;
GLuint sampleCount;
if( query < 0 )
return 1;
if( !R_OcclusionQueryIssued( query ) )
return 1;
query = r_occlusionQueries[query];
pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
if( !available && wait )
{
int n = 0;
do
{
n++;
pglGetQueryObjectivARB( query, GL_QUERY_RESULT_AVAILABLE_ARB, &available );
} while( !available && ( n < 10000 ) );
}
if( !available )
return 0;
pglGetQueryObjectuivARB( query, GL_QUERY_RESULT_ARB, &sampleCount );
return sampleCount;
}
/*
===============
R_GetOcclusionQueryResultBool
===============
*/
qboolean R_GetOcclusionQueryResultBool( int type, int key, qboolean wait )
{
int query = R_GetOcclusionQueryNum( type, key );
if( query >= 0 && R_OcclusionQueryIssued( query ) )
{
if( R_GetOcclusionQueryResult( query, wait ) )
return true;
return false;
}
return true;
}
/*
===============
R_ShutdownOcclusionQueries
===============
*/
void R_ShutdownOcclusionQueries( void )
{
r_occlusionShader = NULL;
if( !GL_Support( R_OCCLUSION_QUERIES_EXT ))
return;
pglDeleteQueriesARB( MAX_OQ_TOTAL, r_occlusionQueries );
r_occludersQueued = false;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,704 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// r_draw.c - draw 2d pictures
//=======================================================================
#include "r_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
#include "triangleapi.h"
#define MAX_TRIVERTS 2048
#define MAX_TRIELEMS MAX_TRIVERTS * 6
#define MAX_TRIANGLES MAX_TRIELEMS / 3
static vec4_t tri_vertex[MAX_TRIVERTS];
static vec4_t tri_normal[MAX_TRIVERTS];
static vec2_t tri_coords[MAX_TRIVERTS];
static rgba_t tri_colors[MAX_TRIVERTS];
static elem_t tri_elems[MAX_TRIELEMS];
static mesh_t tri_mesh;
meshbuffer_t tri_mbuffer;
tristate_t triState;
static vec4_t pic_xyz[4] = { {0,0,0,1}, {0,0,0,1}, {0,0,0,1}, {0,0,0,1} };
static vec2_t pic_st[4];
static rgba_t pic_colors[4];
static mesh_t pic_mesh = { 4, 6, pic_xyz, pic_xyz, NULL, NULL, pic_st, NULL, pic_colors, NULL, NULL };
meshbuffer_t pic_mbuffer;
/*
===============
R_DrawSetColor
===============
*/
void R_DrawSetColor( const rgba_t color )
{
if( color ) Vector4Copy( color, glState.draw_color );
else Vector4Set( glState.draw_color, 255, 255, 255, 255 );
}
/*
===============
R_DrawStretchPic
===============
*/
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t handle )
{
int bcolor;
ref_shader_t *shader;
static int oldframe;
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
return;
// lower-left
Vector2Set( pic_xyz[0], x, y );
Vector2Set( pic_st[0], s1, t1 );
Vector4Copy( glState.draw_color, pic_colors[0] );
bcolor = *(int *)pic_colors[0];
// lower-right
Vector2Set( pic_xyz[1], x+w, y );
Vector2Set( pic_st[1], s2, t1 );
*(int *)pic_colors[1] = bcolor;
// upper-right
Vector2Set( pic_xyz[2], x+w, y+h );
Vector2Set( pic_st[2], s2, t2 );
*(int *)pic_colors[2] = bcolor;
// upper-left
Vector2Set( pic_xyz[3], x, y+h );
Vector2Set( pic_st[3], s1, t2 );
*(int *)pic_colors[3] = bcolor;
if( pic_mbuffer.shaderkey != (int)shader->sortkey || -pic_mbuffer.infokey-1+4 > MAX_ARRAY_VERTS )
{
if( pic_mbuffer.shaderkey )
{
pic_mbuffer.infokey = -1;
R_RenderMeshBuffer( &pic_mbuffer );
}
}
tr.iRenderMode = glState.draw_rendermode;
pic_mbuffer.shaderkey = shader->sortkey;
pic_mbuffer.infokey -= 4;
R_PushMesh( &pic_mesh, MF_TRIFAN|shader->features | ( r_shownormals->integer ? MF_NORMALS : 0 ));
if( oldframe != glState.draw_frame )
{
if( pic_mbuffer.shaderkey != shader->sortkey )
{
// will be rendering on next call
oldframe = glState.draw_frame;
return;
}
if( pic_mbuffer.shaderkey )
{
pic_mbuffer.infokey = -1;
R_RenderMeshBuffer( &pic_mbuffer );
}
oldframe = glState.draw_frame;
}
}
/*
=================
R_ResampleRaw
=================
*/
static byte *R_ResampleRaw( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight )
{
uint frac, fracStep;
uint *in = (uint *)source;
uint p1[0x1000], p2[0x1000];
byte *pix1, *pix2, *pix3, *pix4;
uint *inRow1, *inRow2, *out;
static byte *resampled = NULL;
int i, x, y;
// clean frames doesn't contain raw buffer
if( !source ) return NULL;
resampled = Mem_Realloc( r_temppool, resampled, outWidth * outHeight * 4 );
out = (uint *)resampled;
fracStep = inWidth * 0x10000 / outWidth;
frac = fracStep >> 2;
for( i = 0; i < outWidth; i++ )
{
p1[i] = 4 * (frac >> 16);
frac += fracStep;
}
frac = (fracStep >> 2) * 3;
for( i = 0; i < outWidth; i++ )
{
p2[i] = 4 * (frac >> 16);
frac += fracStep;
}
for( y = 0; y < outHeight; y++, out += outWidth )
{
inRow1 = in + inWidth * (int)(((float)y + 0.25) * inHeight/outHeight);
inRow2 = in + inWidth * (int)(((float)y + 0.75) * inHeight/outHeight);
for( x = 0; x < outWidth; x++ )
{
pix1 = (byte *)inRow1 + p1[x];
pix2 = (byte *)inRow1 + p2[x];
pix3 = (byte *)inRow2 + p1[x];
pix4 = (byte *)inRow2 + p2[x];
((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2;
((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2;
((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2;
((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2;
}
}
return resampled;
}
/*
=============
R_DrawStretchRaw
=============
*/
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty )
{
byte *raw;
if( !GL_Support( R_ARB_TEXTURE_NPOT_EXT ))
{
int width = 1, height = 1;
// check the dimensions
while( width < cols ) width <<= 1;
while( height < rows ) height <<= 1;
if( cols != width || rows != height )
{
raw = R_ResampleRaw( data, cols, rows, width, height );
cols = width;
rows = height;
}
}
else
{
raw = (byte *)data;
}
if( cols > glConfig.max_2d_texture_size )
Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", cols, glConfig.max_2d_texture_size );
if( rows > glConfig.max_2d_texture_size )
Host_Error( "R_DrawStretchRaw: size exceeds hardware limits (%i > %i)\n", rows, glConfig.max_2d_texture_size );
// draw logo may be called between two draw pic calls.
// so we need flush it here
if( pic_mbuffer.infokey != -1 )
{
R_RenderMeshBuffer( &pic_mbuffer );
pic_mbuffer.infokey = -1;
}
GL_Bind( 0, tr.cinTexture );
if( cols == tr.cinTexture->width && rows == tr.cinTexture->height )
{
if( dirty ) pglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_BGRA, GL_UNSIGNED_BYTE, raw );
}
else
{
tr.cinTexture->width = cols;
tr.cinTexture->height = rows;
if( dirty ) pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, cols, rows, 0, GL_BGRA, GL_UNSIGNED_BYTE, raw );
}
R_CheckForErrors();
pglBegin( GL_QUADS );
pglTexCoord2f( 0, 0 );
pglVertex2f( x, y );
pglTexCoord2f( 1, 0 );
pglVertex2f( x + w, y );
pglTexCoord2f( 1, 1 );
pglVertex2f( x + w, y + h );
pglTexCoord2f( 0, 1 );
pglVertex2f( x, y + h );
pglEnd();
}
void R_DrawGetParms( int *w, int *h, int *f, int frame, shader_t handle )
{
ref_shader_t *shader;
int cur = 0;
if( !w && !h && !f ) return;
// assume error
if( w ) *w = 0;
if( h ) *h = 0;
if( f ) *f = 1;
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
return;
if( !shader->num_stages || !shader->stages[0].textures[0] )
return;
if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 )
cur = bound( 0, frame, shader->stages[0].num_textures );
if( w ) *w = (int)shader->stages[0].textures[cur]->srcWidth;
if( h ) *h = (int)shader->stages[0].textures[cur]->srcHeight;
if( f ) *f = (int)shader->stages[0].num_textures;
}
void R_DrawSetParms( shader_t handle, int rendermode, int frame )
{
ref_shader_t *shader;
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]) || !shader->num_stages )
return;
if( glState.draw_rendermode != rendermode )
{
if( pic_mbuffer.shaderkey )
{
pic_mbuffer.infokey = -1;
R_RenderMeshBuffer( &pic_mbuffer );
}
}
if( triState.currentRenderMode != rendermode )
{
if( pic_mbuffer.shaderkey )
{
pic_mbuffer.infokey = -1;
R_RenderMeshBuffer( &pic_mbuffer );
}
}
glState.draw_rendermode = rendermode;
if( !shader->stages[0].num_textures )
return;
// change frame if need
if( shader->stages[0].flags & SHADERSTAGE_FRAMES )
{
// make sure what frame inbound
glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures - 1 );
}
}
/*
=============================================================
TRIAPI IMPLEMENTATION
=============================================================
*/
static void Tri_ClearBounds( void )
{
// clear bounds that uses for polygon lighting
VectorClear( triState.lightingOrigin );
ClearBounds( triState.mins, triState.maxs );
}
static void Tri_DrawPolygon( void )
{
ref_shader_t *shader;
static int i, oldframe;
shader = &r_shaders[triState.currentShader];
tri_mesh.numVerts = triState.numVertex;
tri_mesh.numElems = triState.numIndex;
if( triState.hasNormals )
tri_mesh.normalsArray = tri_normal;
else tri_mesh.normalsArray = NULL; // no normals
if( triState.numColor == 1 )
{
// global color for all vertexes
for( i = 0; i < triState.numVertex - 1; i++ )
Vector4Copy( tri_colors[0], tri_colors[i+1] );
}
// compute lightingOrigin
VectorAverage( triState.mins, triState.maxs, triState.lightingOrigin );
tri_mesh.vertexArray = tri_vertex;
tri_mesh.stCoordArray = tri_coords;
tri_mesh.colorsArray = tri_colors;
tri_mesh.elems = tri_elems;
if( tri_mbuffer.shaderkey != (int)shader->sortkey || -tri_mbuffer.infokey-1+256 > MAX_ARRAY_VERTS )
{
if( tri_mbuffer.shaderkey )
{
tri_mbuffer.infokey = -1;
R_RenderMeshBuffer( &tri_mbuffer );
Tri_ClearBounds();
}
}
tr.iRenderMode = triState.currentRenderMode;
tri_mbuffer.shaderkey = shader->sortkey;
tri_mbuffer.infokey -= triState.numVertex;
triState.features = shader->features;
triState.features |= MF_COLORS;
if( r_shownormals->integer || triState.hasNormals )
triState.features |= MF_NORMALS;
if( triState.noCulling )
triState.features |= MF_NOCULL;
R_PushMesh( &tri_mesh, triState.features );
if( oldframe != glState.draw_frame )
{
if( tri_mbuffer.shaderkey != shader->sortkey )
{
// will be rendering on next call
oldframe = glState.draw_frame;
return;
}
if( tri_mbuffer.shaderkey )
{
tri_mbuffer.infokey = -1;
R_RenderMeshBuffer( &tri_mbuffer );
Tri_ClearBounds();
}
oldframe = glState.draw_frame;
}
triState.numVertex = triState.numIndex = triState.numColor = 0;
}
static void Tri_CheckOverflow( int numIndices, int numVertices )
{
if( numIndices > MAX_TRIELEMS )
Host_Error( "Tri_Overflow: %i > MAX_TRIELEMS\n", numIndices );
if( numVertices > MAX_TRIVERTS )
Host_Error( "Tri_Overflow: %i > MAX_TRIVERTS\n", numVertices );
if( triState.numIndex + numIndices <= MAX_TRIELEMS && triState.numVertex + numVertices <= MAX_TRIVERTS )
return;
Tri_DrawPolygon();
}
void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn )
{
// ignore fog calls from TriApi callbacks
// to avoid strange artefacts and other issues
if( triState.fActive ) return;
// change fog params
triState.fogColor[0] = bound( 0.0f, flFogColor[0], 1.0f );
triState.fogColor[1] = bound( 0.0f, flFogColor[1], 1.0f );
triState.fogColor[2] = bound( 0.0f, flFogColor[2], 1.0f );
triState.fogColor[3] = 1.0f;
triState.fogStartDist = min( flStart, flEnd );
triState.fogEndDist = max( flStart, flEnd );
triState.fogEnabled = bOn;
}
void Tri_CullFace( int mode )
{
if( mode == TRI_FRONT )
triState.noCulling = false;
else if( mode == TRI_NONE )
triState.noCulling = true;
}
void Tri_RenderMode( const int mode )
{
if( triState.currentRenderMode != mode )
{
if( tri_mbuffer.shaderkey )
{
tri_mbuffer.infokey = -1;
R_RenderMeshBuffer( &tri_mbuffer );
Tri_ClearBounds();
}
}
triState.currentRenderMode = mode;
}
void Tri_Vertex3f( const float x, const float y, const float z )
{
uint oldIndex = triState.numIndex;
switch( triState.drawMode )
{
case TRI_LINES:
tri_elems[triState.numIndex++] = triState.numVertex;
if( triState.vertexState++ == 1 )
{
Tri_Vertex3f( x + 1, y + 1, z + 1 );
triState.vertexState = 0;
triState.checkFlush = true; // flush for long sequences of quads.
}
break;
case TRI_TRIANGLES:
tri_elems[triState.numIndex++] = triState.numVertex;
if( triState.vertexState++ == 2 )
{
triState.vertexState = 0;
triState.checkFlush = true; // flush for long sequences of triangles.
}
break;
case TRI_QUADS:
if( triState.vertexState++ < 3 )
{
tri_elems[triState.numIndex++] = triState.numVertex;
}
else
{
// we've already done triangle (0, 1, 2), now draw (2, 3, 0)
tri_elems[triState.numIndex++] = triState.numVertex - 1;
tri_elems[triState.numIndex++] = triState.numVertex;
tri_elems[triState.numIndex++] = triState.numVertex - 3;
triState.vertexState = 0;
triState.checkFlush = true; // flush for long sequences of quads.
}
break;
case TRI_TRIANGLE_STRIP:
if( triState.numVertex + triState.vertexState > MAX_TRIVERTS )
{
// This is a strip that's too big for us to buffer.
// (We can't just flush the buffer because we have to keep
// track of the last two vertices.
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState );
}
if( triState.numIndex > MAX_TRIELEMS )
{
// This is a strip that's too big for us to buffer.
// (We can't just flush the buffer because we have to keep
// track of the last two vertices.
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIELEMS\n", triState.numIndex );
}
if( triState.vertexState++ < 3 )
{
tri_elems[triState.numIndex++] = triState.numVertex;
}
else
{
// flip triangles between clockwise and counter clockwise
if( triState.vertexState & 1 )
{
// draw triangle [n-2 n-1 n]
tri_elems[triState.numIndex++] = triState.numVertex - 2;
tri_elems[triState.numIndex++] = triState.numVertex - 1;
tri_elems[triState.numIndex++] = triState.numVertex;
}
else
{
// draw triangle [n-1 n-2 n]
tri_elems[triState.numIndex++] = triState.numVertex - 1;
tri_elems[triState.numIndex++] = triState.numVertex - 2;
tri_elems[triState.numIndex++] = triState.numVertex;
}
}
break;
case TRI_POLYGON:
case TRI_TRIANGLE_FAN: // same as polygon
if( triState.numVertex + triState.vertexState > MAX_TRIVERTS )
{
// This is a polygon or fan that's too big for us to buffer.
// (We can't just flush the buffer because we have to keep
// track of the starting vertex.
Host_Error( "Tri_Vertex3f: overflow: %i > MAX_TRIVERTS\n", triState.numVertex + triState.vertexState );
}
if( triState.vertexState++ < 3 )
{
tri_elems[triState.numIndex++] = triState.numVertex;
}
else
{
// draw triangle [0 n-1 n]
tri_elems[triState.numIndex++] = triState.numVertex - ( triState.vertexState - 1 );
tri_elems[triState.numIndex++] = triState.numVertex - 1;
tri_elems[triState.numIndex++] = triState.numVertex;
}
break;
default:
Host_Error( "Tri_SetVertex: unknown mode: %i\n", triState.drawMode );
break;
}
// copy current vertex
tri_vertex[triState.numVertex][0] = x;
tri_vertex[triState.numVertex][1] = y;
tri_vertex[triState.numVertex][2] = z;
tri_vertex[triState.numVertex][3] = 1;
// for compute lighting origin
AddPointToBounds( tri_vertex[triState.numVertex], triState.mins, triState.maxs );
triState.numVertex++;
// flush buffer if needed
if( triState.checkFlush )
Tri_CheckOverflow( triState.numIndex - oldIndex, triState.vertexState );
}
void Tri_Color4ub( const byte r, const byte g, const byte b, const byte a )
{
tri_colors[triState.numVertex][0] = r;
tri_colors[triState.numVertex][1] = g;
tri_colors[triState.numVertex][2] = b;
tri_colors[triState.numVertex][3] = a;
triState.numColor++;
}
void Tri_Normal3f( const float x, const float y, const float z )
{
triState.hasNormals = true; // curstate has normals
tri_normal[triState.numVertex][0] = x;
tri_normal[triState.numVertex][1] = y;
tri_normal[triState.numVertex][2] = z;
tri_normal[triState.numVertex][3] = 1;
}
void Tri_TexCoord2f( const float u, const float v )
{
tri_coords[triState.numVertex][0] = u;
tri_coords[triState.numVertex][1] = v;
}
void Tri_Bind( shader_t handle, int frame )
{
ref_shader_t *shader;
if( handle < 0 || handle > MAX_SHADERS || !(shader = &r_shaders[handle]))
{
MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle );
return;
}
if( !shader->num_stages || !shader->stages[0].textures[0] )
{
MsgDev( D_ERROR, "TriBind: bad shader %i\n", handle );
return;
}
triState.currentShader = handle;
// FIXME: scan stages while( frame < stage->num_textures ) ?
if( shader->stages[0].textures[0] && shader->stages[0].num_textures && frame > 0 )
glState.draw_frame = bound( 0, frame, shader->stages[0].num_textures );
}
void Tri_Begin( int mode )
{
triState.drawMode = mode;
triState.vertexState = 0;
triState.checkFlush = false;
triState.hasNormals = false;
}
void Tri_End( void )
{
if( triState.numIndex )
Tri_DrawPolygon();
}
void Tri_RenderCallback( int fTrans )
{
if( !RI.drawWorld ) return;
triState.fActive = true;
if( fTrans ) GL_SetState( GLSTATE_NO_DEPTH_TEST );
R_LoadIdentity ();
Tri_ClearBounds ();
pglColor4f( 1, 1, 1, 1 );
RI.currententity = RI.previousentity = NULL;
RI.currentmodel = NULL;
tri_mbuffer.infokey = -1;
tri_mbuffer.shaderkey = 0;
triState.numColor = 0;
ri.DrawTriangles( fTrans );
// fulsh remaining tris
if( tri_mbuffer.infokey != -1 )
{
R_RenderMeshBuffer( &tri_mbuffer );
tri_mbuffer.infokey = -1;
}
triState.fActive = false;
}
/*
===============
R_Set2DMode
===============
*/
void R_Set2DMode( qboolean enable )
{
if( enable )
{
if( glState.in2DMode )
return;
// set 2D virtual screen size
pglScissor( 0, 0, glState.width, glState.height );
pglViewport( 0, 0, glState.width, glState.height );
pglMatrixMode( GL_PROJECTION );
pglLoadIdentity();
pglOrtho( 0, glState.width, glState.height, 0, -99999, 99999 );
pglMatrixMode( GL_MODELVIEW );
pglLoadIdentity();
GL_Cull( 0 );
GL_SetState( GLSTATE_NO_DEPTH_TEST );
pglColor4f( 1, 1, 1, 1 );
glState.in2DMode = true;
RI.currententity = RI.previousentity = NULL;
RI.currentmodel = NULL;
pic_mbuffer.infokey = -1;
pic_mbuffer.shaderkey = 0;
// reset TriApi state too in case we want use it in 2d mode
Tri_ClearBounds ();
tri_mbuffer.infokey = -1;
tri_mbuffer.shaderkey = 0;
triState.numColor = 0;
triState.fActive = true;
}
else
{
if( pic_mbuffer.infokey != -1 )
{
R_RenderMeshBuffer( &pic_mbuffer );
pic_mbuffer.infokey = -1;
}
// fulsh remaining tris
if( tri_mbuffer.infokey != -1 )
{
R_RenderMeshBuffer( &tri_mbuffer );
tri_mbuffer.infokey = -1;
}
triState.fActive = false;
glState.in2DMode = false;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,873 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
#ifndef __R_LOCAL_H__
#define __R_LOCAL_H__
#include <windows.h>
#include "launch_api.h"
#include "engine_api.h"
#include "render_api.h"
#include "pmtrace.h"
#include "entity_types.h"
#if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
# define ALIGN(x) __declspec(align(16))
#else
# define ALIGN(x)
#endif
#include "r_opengl.h"
extern stdlib_api_t com; // engine toolbox
extern render_imp_t ri;
extern byte *r_temppool;
#define Host_Error com.error
typedef unsigned int elem_t;
typedef enum { RT_NONE, RT_MODEL, RT_PORTALSURFACE, NUM_RTYPES } refEntityType_t;
/*
skins will be outline flood filled and mip mapped
pics and sprites with alpha will be outline flood filled
pic won't be mip mapped
model skin
sprite frame
wall texture
pic
*/
typedef enum
{
TEX_UNKNOWN = 0, // not passed with R_GetPixelFormat, ignore it
TEX_SYSTEM, // generated by engine
TEX_NOMIP, // hud pics, menu etc
TEX_GENERIC, // models, sprites etc
TEX_LIGHTMAP, // lightmap textures
TEX_ALPHA, // with alpha-channel
TEX_SKYBOX, // skybox textures
} texType_t;
typedef enum
{
TF_STATIC = BIT(0), // don't free until Shader_FreeUnused()
TF_NOPICMIP = BIT(1), // ignore r_picmip resample rules
TF_UNCOMPRESSED = BIT(2), // don't compress texture in video memory
TF_CUBEMAP = BIT(3), // it's cubemap texture
TF_NORMALMAP = BIT(4), // needs to be merged with depthmap
TF_DEPTHMAP = BIT(5), // custom texture filter used
TF_INTENSITY = BIT(6),
TF_ALPHA = BIT(7),
TF_SKYSIDE = BIT(8),
TF_CLAMP = BIT(9),
TF_NOMIPMAP = BIT(10),
TF_NEAREST = BIT(11), // disable texfilter
TF_LIGHTMAP = BIT(12), // no resample etc
} texFlags_t;
#define TF_PORTALMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP )
#define TF_SHADOWMAP ( TF_NOMIPMAP|TF_UNCOMPRESSED|TF_NOPICMIP|TF_CLAMP|TF_DEPTHMAP )
typedef struct texture_s
{
string name; // game path, including extension
int srcWidth; // source dims, used for mipmap loading
int srcHeight;
int srcFlags; // rgbdata flags
int width; // upload width\height
int height;
texType_t texType; // just for debug
texFlags_t flags;
size_t size; // upload size for debug targets
GLint format; // PFDesc[type].glType
GLuint target; // glTarget
GLuint texnum; // gl texture binding
GLint samples; // gl samples
int touchFrame; // 0 = free
struct texture_s *nextHash;
} texture_t;
enum
{
TEXTURE_UNIT0,
TEXTURE_UNIT1,
TEXTURE_UNIT2,
TEXTURE_UNIT3,
TEXTURE_UNIT4,
TEXTURE_UNIT5,
TEXTURE_UNIT6,
TEXTURE_UNIT7,
MAX_TEXTURE_UNITS
};
#define FOG_TEXTURE_WIDTH 256
#define FOG_TEXTURE_HEIGHT 32
#define LIGHTMAP_TEXTURE_WIDTH 256
#define LIGHTMAP_TEXTURE_HEIGHT 256
#define VID_DEFAULTMODE "3"
#define SHADOW_PLANAR 1
#define SHADOW_MAPPING 2
#define LM_STYLES 4 // MAXLIGHTMAPS
#define MAX_ENTITIES 2048 // per one frame
#define MAX_POLY_VERTS 3000
#define MAX_POLYS 2048
typedef struct mplane_s
{
vec3_t normal;
float dist;
short type; // for fast side tests
short signbits; // signx + (signy<<1) + (signz<<1)
} mplane_t;
//===================================================================
#include "r_math.h"
#include "r_mesh.h"
#include "r_shader.h"
#include "r_backend.h"
#include "r_shadow.h"
#include "r_model.h"
#define BACKFACE_EPSILON 0.01
#define Z_NEAR 4
#define SIDE_FRONT 0
#define SIDE_BACK 1
#define SIDE_ON 2
// renderer flags
#define RDF_PORTALINVIEW BIT( 0 ) // draw portal pass
#define RDF_SKYPORTALINVIEW BIT( 1 ) // draw skyportal instead of regular sky
#define RP_NONE 0x0
#define RP_MIRRORVIEW 0x1 // lock pvs at vieworg
#define RP_PORTALVIEW 0x2
#define RP_ENVVIEW 0x4
#define RP_NOSKY 0x8
#define RP_SKYPORTALVIEW 0x10
#define RP_PORTALCAPTURED 0x20
#define RP_PORTALCAPTURED2 0x40
#define RP_OLDVIEWLEAF 0x80
#define RP_SHADOWMAPVIEW 0x100
#define RP_FLIPFRONTFACE 0x200
#define RP_WORLDSURFVISIBLE 0x400
#define RP_CLIPPLANE 0x800
#define RP_TRISOUTLINES 0x1000
#define RP_SHOWNORMALS 0x2000
#define RP_NONVIEWERREF ( RP_PORTALVIEW|RP_MIRRORVIEW|RP_ENVVIEW|RP_SKYPORTALVIEW|RP_SHADOWMAPVIEW )
#define RP_LOCALCLIENT(e) (ri.GetLocalPlayer() && ((e)->index == ri.GetLocalPlayer()->index && e->lerp->player ))
#define RP_FOLLOWENTITY(e) (((e)->movetype == MOVETYPE_FOLLOW && (e)->parent))
#define MOD_ALLOWBUMP() (r_lighting_models_followdeluxe->integer ? mapConfig.deluxeMappingEnabled : GL_Support( R_SHADER_GLSL100_EXT ))
//====================================================
typedef struct
{
vec3_t origin;
vec3_t color; // dlight color
float intensity; // cdlight->radius
vec3_t mins, maxs;
ref_shader_t *shader;
int flags; // misc flags
} ref_dlight_t;
typedef struct
{
vec3_t rgb; // 0.0 - 2.0
float white; // highest of RGB
} lightstyle_t;
// FIXME: compress this as much as possible
typedef struct ref_entity_s
{
uint ent_type; // entity type
uint m_nCachedFrameCount;// keep current render frame
int index; // viewmodel has entindex -1
refEntityType_t rtype;
qboolean doOcclusionTest; // check this entity for occlusion
struct ref_model_s *model; // opaque type outside refresh
struct ref_entity_s *parent; // link to parent entity (FOLLOW or weaponmodel)
struct cl_entity_s *lerp; // pointer to client entity
float framerate; // custom framerate
float frame;
int body;
int skin;
int movetype; // entity moving type
float scale;
byte *mempool; // studio mempool
void *extradata; // studiomodel bones, etc
// misc
rgb_t rendercolor; // hl1 rendercolor
byte renderamt; // hl1 alphavalues
int rendermode; // hl1 rendermode
int renderfx; // server will be translate hl1 values into flags
int colormap; // q1 and hl1 model colormap (can applied for sprites)
int flags; // q1 effect flags, EF_LIGHT, EF_DIMLIGHT etc
// client gait sequence (local stuff)
int gaitsequence; // client->sequence + yaw
// most recent data
vec3_t axis[3];
vec3_t angles;
vec3_t movedir; // forward vector that computed on a server
vec3_t origin, origin2;
vec3_t lightingOrigin;
float waveHeight;
// RT_SPRITE stuff
struct ref_shader_s *customShader; // client drawing stuff
float radius; // used as RT_SPRITE's radius
} ref_entity_t;
typedef struct skyportal_s
{
float fov;
float scale;
vec3_t vieworg;
vec3_t viewangles;
} skyportal_t;
typedef struct
{
int params; // rendering parameters
int rdflags; // actual rendering flags
ref_params_t refdef;
int scissor[4];
int viewport[4];
float lerpFrac; // lerpfraction
qboolean drawWorld; // ignore world for drawing PlayerModel
qboolean thirdPerson; // thirdperson camera is enabled
meshlist_t *meshlist; // meshes to be rendered
meshbuffer_t **surfmbuffers; // pointers to meshbuffers of world surfaces
uint shadowBits;
shadowGroup_t *shadowGroup;
ref_entity_t *currententity;
ref_model_t *currentmodel;
ref_entity_t *previousentity;
//
// view origin
//
vec3_t viewOrigin;
vec3_t viewAxis[3];
vec_t *vup, *vpn, *vright;
mplane_t frustum[6];
float farClip;
uint clipFlags;
vec3_t visMins, visMaxs;
matrix4x4 objectMatrix;
matrix4x4 worldviewMatrix;
matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix
matrix4x4 projectionMatrix;
matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix
float skyMins[2][6];
float skyMaxs[2][6];
skyportal_t skyportal; // skyportal params
float fog_dist_to_eye[256]; // MAX_MAP_FOGS
vec3_t pvsOrigin;
mplane_t clipPlane;
mplane_t portalPlane;
} refinst_t;
//====================================================
extern int r_pvsframecount;
extern int r_framecount;
extern int r_framecount2;
extern int c_brush_polys, c_world_leafs;
extern double r_mark_leaves, r_world_node;
extern double r_add_polys, r_add_entities;
extern double r_sort_meshes, r_draw_meshes;
extern msurface_t *r_debug_surface;
extern const char *r_debug_hitbox;
extern int gl_filter_min, gl_filter_max;
#define MAX_RSPEEDSMSGSIZE 1024
extern char r_speeds_msg[MAX_RSPEEDSMSGSIZE];
extern ref_model_t *cl_models[MAX_MODELS];
extern float gldepthmin, gldepthmax;
//
// screen size info
//
extern uint r_numEntities;
extern ref_entity_t r_entities[MAX_ENTITIES];
extern uint r_numDlights;
extern ref_dlight_t r_dlights[MAX_DLIGHTS];
extern uint r_numPolys;
extern poly_t r_polys[MAX_POLYS];
extern lightstyle_t r_lightStyles[MAX_LIGHTSTYLES];
extern ref_params_t r_lastRefdef;
extern mleaf_t *r_viewleaf, *r_oldviewleaf;
extern mleaf_t *r_viewleaf2, *r_oldviewleaf2;
extern float r_farclip_min, r_farclip_bias;
extern ref_entity_t *r_worldent;
extern ref_model_t *r_worldmodel;
extern mbrushmodel_t *r_worldbrushmodel;
extern convar_t *r_colorbits;
extern convar_t *r_depthbits;
extern convar_t *r_stencilbits;
extern convar_t *r_norefresh;
extern convar_t *r_drawentities;
extern convar_t *r_drawworld;
extern convar_t *r_speeds;
extern convar_t *r_drawelements;
extern convar_t *r_fullbright;
extern convar_t *r_lightmap;
extern convar_t *r_novis;
extern convar_t *r_nocull;
extern convar_t *r_ignorehwgamma;
extern convar_t *r_overbrightbits;
extern convar_t *r_vertexbuffers;
extern convar_t *r_lefthand;
extern convar_t *r_physbdebug;
extern convar_t *r_check_errors;
extern convar_t *r_allow_software;
extern convar_t *r_frontbuffer;
extern convar_t *r_adjust_fov;
extern convar_t *r_width;
extern convar_t *r_height;
extern convar_t *r_flares;
extern convar_t *r_flaresize;
extern convar_t *r_flarefade;
extern convar_t *r_spriteflares;
extern convar_t *r_cullflares;
extern convar_t *r_dynamiclight;
extern convar_t *r_coronascale;
extern convar_t *r_detailtextures;
extern convar_t *r_subdivisions;
extern convar_t *r_faceplanecull;
extern convar_t *gl_wireframe;
extern convar_t *r_shownormals;
extern convar_t *r_showtextures;
extern convar_t *r_draworder;
extern convar_t *r_fastsky;
extern convar_t *r_portalonly;
extern convar_t *r_portalmaps;
extern convar_t *r_portalmaps_maxtexsize;
extern convar_t *r_lighting_bumpscale;
extern convar_t *r_lighting_deluxemapping;
extern convar_t *r_lighting_diffuse2heightmap;
extern convar_t *r_lighting_specular;
extern convar_t *r_lighting_glossintensity;
extern convar_t *r_lighting_glossexponent;
extern convar_t *r_lighting_models_followdeluxe;
extern convar_t *r_lighting_ambientscale;
extern convar_t *r_lighting_directedscale;
extern convar_t *r_lighting_modulate;
extern convar_t *r_offsetmapping;
extern convar_t *r_offsetmapping_scale;
extern convar_t *r_offsetmapping_reliefmapping;
extern convar_t *r_occlusion_queries;
extern convar_t *r_occlusion_queries_finish;
extern convar_t *r_shadows;
extern convar_t *r_shadows_alpha;
extern convar_t *r_shadows_nudge;
extern convar_t *r_shadows_projection_distance;
extern convar_t *r_shadows_maxtexsize;
extern convar_t *r_shadows_pcf;
extern convar_t *r_shadows_self_shadow;
extern convar_t *r_bloom_alpha;
extern convar_t *r_bloom_diamond_size;
extern convar_t *r_bloom_intensity;
extern convar_t *r_bloom_darken;
extern convar_t *r_bloom_sample_size;
extern convar_t *r_bloom_fast_sample;
extern convar_t *r_himodels;
extern convar_t *r_environment_color;
extern convar_t *r_gamma;
extern convar_t *r_texturebits;
extern convar_t *gl_texturemode;
extern convar_t *gl_texture_anisotropy;
extern convar_t *gl_texture_lodbias;
extern convar_t *gl_round_down;
extern convar_t *gl_compress_textures;
extern convar_t *r_decals;
extern convar_t *r_mode;
extern convar_t *r_nobind;
extern convar_t *r_picmip;
extern convar_t *r_skymip;
extern convar_t *gl_clear;
extern convar_t *r_lockpvs;
extern convar_t *r_swapInterval;
extern convar_t *gl_finish;
extern convar_t *gl_delayfinish;
extern convar_t *gl_cull;
extern convar_t *gl_extensions;
extern convar_t *vid_fullscreen;
extern convar_t *vid_multiscreen_head;
extern convar_t *vid_displayfrequency;
//====================================================================
static _inline byte R_FloatToByte( float x )
{
union {
float f;
unsigned int i;
} f2i;
// shift float to have 8bit fraction at base of number
f2i.f = x + 32768.0f;
f2i.i &= 0x7FFFFF;
// then read as integer and kill float bits...
return ( byte )min( f2i.i, 255 );
}
float R_FastSin( float t );
void R_LatLongToNorm( const byte latlong[2], vec3_t out );
void NormToLatLong( const vec3_t normal, byte latlong[2] );
void ColorToBytes( const float *color, byte *colorBytes );
//====================================================================
//
// r_bloom.c
//
void R_InitBloomTextures( void );
void R_BloomBlend( const ref_params_t *fd );
//
// r_cull.c
//
enum
{
OQ_NONE = -1,
OQ_ENTITY,
OQ_PLANARSHADOW,
OQ_SHADOWGROUP,
OQ_CUSTOM
};
#define OCCLUSION_QUERIES_CVAR_HACK( RI ) ( !(r_occlusion_queries->integer == 2 && r_shadows->integer != SHADOW_MAPPING) \
|| ((RI).rdflags & RDF_PORTALINVIEW) )
#define OCCLUSION_QUERIES_ENABLED( RI ) ( GL_Support( R_OCCLUSION_QUERIES_EXT ) && r_occlusion_queries->integer && r_drawentities->integer \
&& !((RI).params & RP_NONVIEWERREF) && ((RI).drawWorld) \
&& OCCLUSION_QUERIES_CVAR_HACK( RI ) )
#define OCCLUSION_OPAQUE_SHADER( s ) (((s)->sort == SORT_OPAQUE ) && ((s)->flags & SHADER_DEPTHWRITE ) && !(s)->numDeforms )
#define OCCLUSION_TEST_ENTITY( e ) (((e)->doOcclusionTest ) || ((e)->ent_type == ET_VIEWENTITY ))
void R_InitOcclusionQueries( void );
void R_BeginOcclusionPass( void );
ref_shader_t *R_OcclusionShader( void );
void R_AddOccludingSurface( msurface_t *surf, ref_shader_t *shader );
int R_GetOcclusionQueryNum( int type, int key );
int R_IssueOcclusionQuery( int query, ref_entity_t *e, vec3_t mins, vec3_t maxs );
qboolean R_OcclusionQueryIssued( int query );
uint R_GetOcclusionQueryResult( int query, qboolean wait );
qboolean R_GetOcclusionQueryResultBool( int type, int key, qboolean wait );
void R_EndOcclusionPass( void );
void R_ShutdownOcclusionQueries( void );
//
// r_draw.c
//
void R_Set2DMode( qboolean enable );
void R_DrawSetColor( const void *data );
void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shadernum );
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean redraw );
void R_DrawSetParms( shader_t handle, int rendermode, int frame );
void R_DrawGetParms( int *w, int *h, int *f, int frame, shader_t shader );
void Tri_RenderMode( const int mode );
void Tri_Normal3f( const float x, const float y, const float z );
void Tri_Vertex3f( const float x, const float y, const float z );
void Tri_Color4ub( const byte r, const byte g, const byte b, const byte a );
void Tri_Fog( float flFogColor[3], float flStart, float flEnd, int bOn );
void Tri_TexCoord2f( const float u, const float v );
void Tri_Bind( shader_t shader, int frame );
void Tri_RenderCallback( int fTrans );
void Tri_CullFace( int mode );
void Tri_Begin( int mode );
void Tri_End( void );
//
// r_image.c
//
void GL_SelectTexture( GLenum tmu );
void GL_Bind( GLenum tmu, texture_t *tex );
void GL_TexEnv( GLenum mode );
void GL_LoadMatrix( const matrix4x4 source );
void GL_LoadTexMatrix( const matrix4x4 m );
void GL_LoadIdentityTexMatrix( void );
void GL_EnableTexGen( int coord, int mode );
void GL_SetTexCoordArrayMode( int mode );
void GL_TexFilter( texture_t *tex );
void R_InitImages( void );
void R_ShutdownImages( void );
void R_InitPortalTexture( texture_t **texture, int id, int screenWidth, int screenHeight );
void R_InitShadowmapTexture( texture_t **texture, int id, int screenWidth, int screenHeight );
void R_FreeImage( texture_t *image );
void R_TextureList_f( void );
void R_SetTextureParameters( void );
void R_ShowTextures( void );
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 );
qboolean VID_ScreenShot( const char *filename, int shot_type );
qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot );
//
// r_light.c
//
void R_BeginBuildingLightmaps( void );
void R_BuildSurfaceLightmap( msurface_t *surf );
void R_EndBuildingLightmaps( void );
void R_UpdateSurfaceLightmap( msurface_t *surf );
void R_LightBounds( const vec3_t origin, float intensity, vec3_t mins, vec3_t maxs );
qboolean R_SurfPotentiallyLit( msurface_t *surf );
uint R_AddSurfDlighbits( msurface_t *surf, uint dlightbits );
void R_AddDynamicLights( uint dlightbits, int state );
void R_LightForEntity( ref_entity_t *e, byte *bArray );
void R_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius );
void R_LightForPoint( const vec3_t point, vec3_t ambientLight );
void R_LightDir( const vec3_t origin, vec3_t lightDir, float radius );
int R_AddSuperLightStyle( const int lightmapNum, const byte *lightmapStyles );
void R_BuildLightGrid( mbrushmodel_t *world );
void R_InitCoronas( void );
void R_DrawCoronas( void );
//
// r_main.c
//
void GL_Cull( int cull );
void GL_SetState( int state );
void GL_FrontFace( int front );
void R_BeginFrame( qboolean clearScene );
void R_EndFrame( void );
void R_RenderScene( const ref_params_t *fd, qboolean drawWorld );
void R_RenderView( const ref_params_t *fd );
void R_ClearScene( void );
qboolean R_CullBox( const vec3_t mins, const vec3_t maxs, const uint clipflags );
qboolean R_CullSphere( const vec3_t centre, const float radius, const uint clipflags );
qboolean R_VisCullBox( const vec3_t mins, const vec3_t maxs );
qboolean R_VisCullSphere( const vec3_t origin, float radius );
int R_CullModel( ref_entity_t *e, vec3_t mins, vec3_t maxs, float radius );
mfog_t *R_FogForSphere( const vec3_t centre, const float radius );
qboolean R_CompletelyFogged( mfog_t *fog, vec3_t origin, float radius );
void R_LoadIdentity( void );
void R_RotateForEntity( ref_entity_t *e );
void R_TranslateForEntity( ref_entity_t *e );
qboolean R_TransformToScreen_Vec3( const vec3_t in, vec3_t out );
void R_TransformVectorToScreen( const ref_params_t *rd, const vec3_t in, vec2_t out );
void R_TransformEntityBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs, vec3_t bbox[8], qboolean local );
qboolean R_SpriteOverflow( void );
qboolean R_PushSpritePoly( const meshbuffer_t *mb );
qboolean R_PushSprite( const meshbuffer_t *mb, int type, float right, float left, float up, float down );
#define NUM_CUSTOMCOLORS 16
void R_InitCustomColors( void );
void R_SetCustomColor( int num, int r, int g, int b );
int R_GetCustomColor( int num );
msurface_t *R_TraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, int flags );
//
// r_mesh.c
//
extern meshlist_t r_worldlist, r_shadowlist;
void R_InitMeshLists( void );
void R_FreeMeshLists( void );
void R_ClearMeshList( meshlist_t *meshlist );
int R_ReAllocMeshList( meshbuffer_t **mb, int minMeshes, int maxMeshes );
meshbuffer_t *R_AddMeshToList( int type, mfog_t *fog, ref_shader_t *shader, int infokey );
void R_AddModelMeshToList( unsigned int modhandle, mfog_t *fog, ref_shader_t *shader, int meshnum );
void R_AllocMeshbufPointers( refinst_t *RI );
void R_SortMeshes( void );
void R_DrawMeshes( void );
void R_DrawTriangleOutlines( qboolean showTris, qboolean showNormals );
void R_DrawPortals( void );
void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size );
void R_DrawSkyPortal( skyportal_t *skyportal, vec3_t mins, vec3_t maxs );
void R_BuildTangentVectors( int numVertexes, vec4_t *xyzArray, vec4_t *normalsArray, vec2_t *stArray, int numTris, elem_t *elems, vec4_t *sVectorsArray );
//
// r_program.c
//
#define DEFAULT_GLSL_PROGRAM "*r_defaultProgram"
#define DEFAULT_GLSL_DISTORTION_PROGRAM "*r_defaultDistortionProgram"
#define DEFAULT_GLSL_SHADOWMAP_PROGRAM "*r_defaultShadowmapProgram"
enum
{
PROGRAM_TYPE_NONE,
PROGRAM_TYPE_MATERIAL,
PROGRAM_TYPE_DISTORTION,
PROGRAM_TYPE_SHADOWMAP,
};
enum
{
PROGRAM_APPLY_LIGHTSTYLE0 = 1 << 0,
PROGRAM_APPLY_LIGHTSTYLE1 = 1 << 1,
PROGRAM_APPLY_LIGHTSTYLE2 = 1 << 2,
PROGRAM_APPLY_LIGHTSTYLE3 = 1 << 3,
PROGRAM_APPLY_SPECULAR = 1 << 4,
PROGRAM_APPLY_DIRECTIONAL_LIGHT = 1 << 5,
PROGRAM_APPLY_FB_LIGHTMAP = 1 << 6,
PROGRAM_APPLY_OFFSETMAPPING = 1 << 7,
PROGRAM_APPLY_RELIEFMAPPING = 1 << 8,
PROGRAM_APPLY_AMBIENT_COMPENSATION = 1 << 9,
PROGRAM_APPLY_DECAL = 1 << 10,
PROGRAM_APPLY_BASETEX_ALPHA_ONLY = 1 << 11,
PROGRAM_APPLY_EYEDOT = 1 << 12,
PROGRAM_APPLY_DISTORTION_ALPHA = 1 << 13,
PROGRAM_APPLY_PCF2x2 = 1 << 14,
PROGRAM_APPLY_PCF3x3 = 1 << 15,
PROGRAM_APPLY_BRANCHING = 1 << 16,
PROGRAM_APPLY_CLIPPING = 1 << 17,
PROGRAM_APPLY_NO_HALF_TYPES = 1 << 18
};
void R_InitGLSLPrograms( void );
int R_FindGLSLProgram( const char *name );
int R_RegisterGLSLProgram( const char *name, const char *string, unsigned int features );
int R_GetProgramObject( int elem );
void R_UpdateProgramUniforms( int elem, vec3_t eyeOrigin, vec3_t lightOrigin, vec3_t lightDir,
vec4_t ambient, vec4_t diffuse, ref_style_t *lightStyle, qboolean frontPlane, int TexWidth, int TexHeight,
float projDistance, float offsetmappingScale );
void R_ShutdownGLSLPrograms( void );
void R_ProgramList_f( void );
void R_ProgramDump_f( void );
//
// r_decals.c
//
void R_InitDecals( void );
void R_ClearDecals( void );
void R_ShutdownDecals( void );
qboolean R_DecalShoot( shader_t texture, int entity, int modelIndex, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration );
decal_t *R_DecalFromMeshbuf( const meshbuffer_t *mb );
int R_CreateDecalList( decallist_t *pList, qboolean changelevel );
void R_AddSurfaceDecals( msurface_t *surf );
void R_PushDecal( const meshbuffer_t *mb );
void R_DecalRemoveAll( shader_t shader );
//
// r_poly.c
//
void R_PushPoly( const meshbuffer_t *mb );
void R_AddPolysToList( void );
msurface_t *R_TransformedTraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int flags );
//
// r_sprite.c
//
void R_SpriteInit( void );
mspriteframe_t *R_GetSpriteFrame( ref_model_t *pModel, int frame, float yawAngle );
ref_shader_t *CL_LoadSprite( const char *szSpriteName );
void R_DrawSpriteModel( const meshbuffer_t *mb );
qboolean R_SpriteOccluded( ref_entity_t *e );
qboolean R_CullSpriteModel( ref_entity_t *e );
void R_SpriteDrawDebug( void );
//
// r_studio.c
//
void R_AddStudioModelToList( ref_entity_t *e );
void R_DrawStudioModel( const meshbuffer_t *mb );
void R_StudioModelBBox( ref_entity_t *e, vec3_t mins, vec3_t maxs );
qboolean R_CullStudioModel( ref_entity_t *e );
void R_StudioRunEvents( ref_entity_t *e );
void R_StudioDrawHitbox( ref_entity_t *e, int iHitbox );
void R_StudioDrawDebug( void );
void R_StudioInit( void );
qboolean R_StudioTrace( ref_entity_t *e, const vec3_t start, const vec3_t end, pmtrace_t *tr );
void R_StudioAllocExtradata( struct cl_entity_s *in, ref_entity_t *e );
void R_StudioFreeAllExtradata( void );
void R_StudioShutdown( void );
//
//
// r_register.c
//
void R_NewMap( void );
qboolean R_Init( qboolean full );
void R_Shutdown( qboolean full );
//
// r_opengl.c
//
void R_RestoreGamma( void );
void R_CheckForErrors_( const char *filename, const int fileline );
#define R_CheckForErrors() R_CheckForErrors_( __FILE__, __LINE__ )
//
// r_surf.c
//
#define MAX_SURF_QUERIES 0x1E0
void R_MarkLeaves( void );
void R_DrawWorld( void );
void R_BmodelDrawDebug( void );
qboolean R_SurfPotentiallyVisible( msurface_t *surf );
qboolean R_CullBrushModel( ref_entity_t *e );
void R_AddBrushModelToList( ref_entity_t *e );
void R_ClearSurfOcclusionQueryKeys( void );
int R_SurfOcclusionQueryKey( ref_entity_t *e, msurface_t *surf );
void R_SurfIssueOcclusionQueries( void );
//
// r_sky.c
//
skydome_t *R_CreateSkydome( byte *mempool, float skyheight, ref_shader_t **farboxShaders, ref_shader_t **nearboxShaders );
void R_FreeSkydome( skydome_t *skydome );
void R_ClearSkyBox( void );
void R_DrawSky( ref_shader_t *shader );
qboolean R_AddSkySurface( msurface_t *fa );
void R_SetupSky( const char *name );
void R_FreeSky( void );
//====================================================================
enum
{
GLSTATE_NONE = 0,
//
// glBlendFunc args
//
GLSTATE_SRCBLEND_ZERO = 1,
GLSTATE_SRCBLEND_ONE = 2,
GLSTATE_SRCBLEND_DST_COLOR = 1|2,
GLSTATE_SRCBLEND_ONE_MINUS_DST_COLOR = 4,
GLSTATE_SRCBLEND_SRC_ALPHA = 1|4,
GLSTATE_SRCBLEND_ONE_MINUS_SRC_ALPHA = 2|4,
GLSTATE_SRCBLEND_DST_ALPHA = 1|2|4,
GLSTATE_SRCBLEND_ONE_MINUS_DST_ALPHA = 8,
GLSTATE_DSTBLEND_ZERO = 16,
GLSTATE_DSTBLEND_ONE = 32,
GLSTATE_DSTBLEND_SRC_COLOR = 16|32,
GLSTATE_DSTBLEND_ONE_MINUS_SRC_COLOR = 64,
GLSTATE_DSTBLEND_SRC_ALPHA = 16|64,
GLSTATE_DSTBLEND_ONE_MINUS_SRC_ALPHA = 32|64,
GLSTATE_DSTBLEND_DST_ALPHA = 16|32|64,
GLSTATE_DSTBLEND_ONE_MINUS_DST_ALPHA = 128,
GLSTATE_BLEND_MTEX = 0x100,
GLSTATE_AFUNC_GT0 = 0x200,
GLSTATE_AFUNC_LT128 = 0x400,
GLSTATE_AFUNC_GE128 = 0x800,
GLSTATE_DEPTHWRITE = 0x1000,
GLSTATE_DEPTHFUNC_EQ = 0x2000,
GLSTATE_OFFSET_FILL = 0x4000,
GLSTATE_NO_DEPTH_TEST = 0x8000,
GLSTATE_MARK_END = 0x10000 // SHADERPASS_MARK_BEGIN
};
#define GLSTATE_MASK ( GLSTATE_MARK_END-1 )
// #define SHADERPASS_SRCBLEND_MASK (((GLSTATE_SRCBLEND_DST_ALPHA)<<1)-GLSTATE_SRCBLEND_ZERO)
#define GLSTATE_SRCBLEND_MASK 0xF
// #define SHADERPASS_DSTBLEND_MASK (((GLSTATE_DSTBLEND_DST_ALPHA)<<1)-GLSTATE_DSTBLEND_ZERO)
#define GLSTATE_DSTBLEND_MASK 0xF0
#define GLSTATE_BLENDFUNC ( GLSTATE_SRCBLEND_MASK|GLSTATE_DSTBLEND_MASK )
#define GLSTATE_ALPHAFUNC ( GLSTATE_AFUNC_GT0|GLSTATE_AFUNC_LT128|GLSTATE_AFUNC_GE128 )
typedef struct
{
float ambient[3];
rgba_t environmentColor;
qboolean deluxeMappingEnabled; // true if deluxeMaps is true and r_lighting_deluxemaps->integer != 0
} mapconfig_t;
extern mapconfig_t mapConfig;
extern refinst_t RI, prevRI;
#endif /*__R_LOCAL_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -1,226 +0,0 @@
/*
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.
*/
// r_math.c
#include "r_local.h"
#include "r_math.h"
#include "mathlib.h"
/*
====================
CalcFov
====================
*/
float CalcFov( float fov_x, float width, float height )
{
float x, half_fov_y;
if( fov_x < 1 || fov_x > 170 )
{
MsgDev( D_ERROR, "CalcFov: bad fov %g!\n", fov_x );
fov_x = 90;
}
x = width / tan( DEG2RAD( fov_x ) * 0.5f );
half_fov_y = atan( height / x );
return RAD2DEG( half_fov_y ) * 2;
}
/*
====================
AdjustFov
====================
*/
void AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x )
{
float x, y;
if( width * 3 == 4 * height || width * 4 == height * 5 )
{
// 4:3 or 5:4 ratio
return;
}
if( lock_x )
{
*fov_y = 2 * atan((width * 3) / (height * 4) * tan (*fov_y * M_PI / 360.0 * 0.5) ) * 360 / M_PI;
return;
}
y = CalcFov( *fov_x, 640, 480 );
x = *fov_x;
*fov_x = CalcFov( y, height, width );
if( *fov_x < x ) *fov_x = x;
else *fov_y = y;
}
/*
=================
CategorizePlane
A slightly more complex version of SignbitsForPlane and PlaneTypeForNormal,
which also tries to fix possible floating point glitches (like -0.00000 cases)
=================
*/
void CategorizePlane( mplane_t *plane )
{
int i;
plane->signbits = 0;
plane->type = PLANE_NONAXIAL;
for( i = 0; i < 3; i++ )
{
if( plane->normal[i] < 0 )
{
plane->signbits |= 1<<i;
if( plane->normal[i] == -1.0f )
{
plane->signbits = (1<<i);
plane->normal[0] = plane->normal[1] = plane->normal[2] = 0;
plane->normal[i] = -1.0f;
break;
}
}
else if( plane->normal[i] == 1.0f )
{
plane->type = i;
plane->signbits = 0;
plane->normal[0] = plane->normal[1] = plane->normal[2] = 0;
plane->normal[i] = 1.0f;
break;
}
}
}
/*
==================
BoxOnPlaneSide
Returns 1, 2, or 1 + 2
==================
*/
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p )
{
float dist1, dist2;
int sides = 0;
// general case
switch( p->signbits )
{
case 0:
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
break;
case 1:
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
break;
case 2:
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
break;
case 3:
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
break;
case 4:
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
dist2 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
break;
case 5:
dist1 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2];
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2];
break;
case 6:
dist1 = p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
dist2 = p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
break;
case 7:
dist1 = p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2];
dist2 = p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2];
break;
default:
// shut up compiler
dist1 = dist2 = 0;
break;
}
if( dist1 >= p->dist )
sides = 1;
if( dist2 < p->dist )
sides |= 2;
return sides;
}
/*
====================
RotatePointAroundVector
====================
*/
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees )
{
float t0, t1;
float angle, c, s;
vec3_t vr, vu, vf;
angle = DEG2RAD( degrees );
com.sincos( angle, &s, &c );
VectorCopy( dir, vf );
VectorVectors( vf, vr, vu );
t0 = vr[0] * c + vu[0] * -s;
t1 = vr[0] * s + vu[0] * c;
dst[0] = (t0 * vr[0] + t1 * vu[0] + vf[0] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[0] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[0] * vf[2]) * point[2];
t0 = vr[1] * c + vu[1] * -s;
t1 = vr[1] * s + vu[1] * c;
dst[1] = (t0 * vr[0] + t1 * vu[0] + vf[1] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[1] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[1] * vf[2]) * point[2];
t0 = vr[2] * c + vu[2] * -s;
t1 = vr[2] * s + vu[2] * c;
dst[2] = (t0 * vr[0] + t1 * vu[0] + vf[2] * vf[0]) * point[0]
+ (t0 * vr[1] + t1 * vu[1] + vf[2] * vf[1]) * point[1]
+ (t0 * vr[2] + t1 * vu[2] + vf[2] * vf[2]) * point[2];
}
/*
=================
PlaneFromPoints
=================
*/
void PlaneFromPoints( vec3_t verts[3], mplane_t *plane )
{
vec3_t v1, v2;
VectorSubtract( verts[1], verts[0], v1 );
VectorSubtract( verts[2], verts[0], v2 );
CrossProduct( v2, v1, plane->normal );
VectorNormalize( plane->normal );
plane->dist = DotProduct( verts[0], plane->normal );
}

View File

@ -1,72 +0,0 @@
/*
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.
*/
#ifndef __R_MATH_H__
#define __R_MATH_H__
// r_math.h
float CalcFov( float fov_x, float width, float height );
int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p );
void AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x );
void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
void PlaneFromPoints( vec3_t verts[3], mplane_t *plane );
void CategorizePlane( mplane_t *plane );
#define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \
((( p )->type < 3 ) ? \
( \
((p)->dist <= (emins)[(p)->type]) ? \
1 \
: \
( \
((p)->dist >= (emaxs)[(p)->type]) ? \
2 \
: \
3 \
) \
) \
: \
BoxOnPlaneSide(( emins ), ( emaxs ), ( p )))
/*
===============
ColorNormalize
===============
*/
_inline float ColorNormalize( const float *in, vec3_t out )
{
float f = max( max( in[0], in[1] ), in[2] );
if( f > 1.0f )
{
f = 1.0f / f;
out[0] = in[0] * f;
out[1] = in[1] * f;
out[2] = in[2] * f;
}
else
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
}
return f;
}
#endif /*__R_MATH_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -1,114 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2009 ©
// r_mesh.h - generic mesh container
//=======================================================================
#ifndef R_MESH_H
#define R_MESH_H
enum
{
MF_NONE = 0,
MF_NORMALS = BIT( 0 ),
MF_STCOORDS = BIT( 1 ),
MF_LMCOORDS = BIT( 2 ),
MF_COLORS = BIT( 3 ),
MF_ENABLENORMALS = BIT( 4 ),
MF_DEFORMVS = BIT( 5 ),
MF_SVECTORS = BIT( 6 ),
MF_TVECTORS = BIT( 7 ),
// global features
MF_NOCULL = BIT( 16 ),
MF_TRIFAN = BIT( 17 ),
MF_NONBATCHED = BIT( 18 ),
MF_KEEPLOCK = BIT( 19 )
};
enum
{
MB_MODEL,
MB_POLY,
MB_DECAL,
MB_CORONA,
MB_MAXTYPES = 4
};
typedef struct mesh_s
{
int numVerts;
int numElems;
vec4_t *vertexArray;
vec4_t *normalsArray;
vec4_t *sVectorsArray;
vec4_t *tVectorsArray;
vec2_t *stCoordArray;
vec2_t *lmCoordArray;
rgba_t *colorsArray;
elem_t *elems;
struct mesh_s *next; // temporary chain of subdivided surfaces
} mesh_t;
#define MB_FOG2NUM( fog ) ((fog) ? ((((int)((fog) - r_worldbrushmodel->fogs))+1) << 2) : 0 )
#define MB_NUM2FOG( num, fog ) ((fog) = r_worldbrushmodel->fogs+(((num)>>2) & 0xFF), (fog) = ( (fog) == r_worldbrushmodel->fogs ? NULL : (fog)-1 ))
#define MB_ENTITY2NUM( ent ) ((int)((ent)-r_entities)<<20 )
#define MB_NUM2ENTITY( num, ent ) (ent = r_entities+(((num)>>20)&MAX_ENTITIES-1))
#define MB_SHADER2NUM( s ) ((s)->sort << 26 ) | ((s) - r_shaders )
#define MB_NUM2SHADER( num, s ) ((s) = r_shaders + ((num) & 0xFFF))
#define MB_NUM2SHADERSORT( num ) (((num) >> 26) & 0x1F )
#define MIN_RENDER_MESHES 2048
typedef struct
{
int shaderkey;
uint sortkey;
int infokey; // surface number or mesh number
union
{
int lastPoly;
uint dlightbits;
uint modhandle;
uint placeTime; // decal createtime
};
uint shadowbits;
} meshbuffer_t;
typedef struct
{
int num_opaque_meshes, max_opaque_meshes;
meshbuffer_t *meshbuffer_opaque;
int num_translucent_meshes, max_translucent_meshes;
meshbuffer_t *meshbuffer_translucent;
int num_portal_opaque_meshes;
int num_portal_translucent_meshes;
} meshlist_t;
enum
{
SKYBOX_RIGHT,
SKYBOX_LEFT,
SKYBOX_FRONT,
SKYBOX_BACK,
SKYBOX_TOP,
SKYBOX_BOTTOM // not used for skydome, but is used for skybox
};
typedef struct
{
float skyHeight;
mesh_t *meshes;
vec2_t *sphereStCoords[6];
vec2_t *linearStCoords[6];
struct ref_shader_s *farboxShaders[6];
struct ref_shader_s *nearboxShaders[6];
} skydome_t;
#endif /*__R_MESH_H__*/

File diff suppressed because it is too large Load Diff

View File

@ -1,356 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
#ifndef R_MODEL_H
#define R_MODEL_H
/*
d*_t structures are on-disk representations
m*_t structures are in-memory
*/
#include "sprite.h"
#include "studio.h"
/*
==============================================================================
BRUSH MODELS
==============================================================================
*/
//
// in memory representation
//
typedef enum
{
mod_bad = -1,
mod_brush,
mod_sprite,
mod_alias,
mod_studio,
mod_world, // added
} modtype_t;
typedef struct
{
vec3_t mins, maxs;
vec3_t origin;
float radius;
int firstnode; // used for lighting bmodels
int firstface;
int numfaces;
int visleafs;
} mmodel_t;
typedef struct
{
ref_shader_t *shader;
mplane_t *visibleplane;
int numplanes;
mplane_t *planes;
} mfog_t;
typedef struct decal_s
{
struct decal_s *pnext; // linked list for each surface
struct msurface_s *psurf; // surface id for persistence / unlinking
ref_shader_t *shader; // decal image
vec3_t position; // location of the decal center in world space.
vec3_t worldPos; // untransformed position, keep for serialization
vec3_t saxis; // direction of the s axis in world space
float dx, dy; // Offsets into surface texture
float scale; // pixel scale
short flags; // decal flags FDECAL_*
short entityIndex; // entity this is attached to
mesh_t *mesh; // cached mesh, created on first decal rendering
// dynamic decals stuff
float fadeDuration; // Negative value means to fade in
float fadeStartTime;
float currentFrame; // for animated decals
rgba_t color;
} decal_t;
// miptex features (will be convert to a shader settings)
#define MIPTEX_CONVEYOR BIT( 0 ) // create conveyour surface
#define MIPTEX_LIQUID BIT( 1 ) // is a liquid
#define MIPTEX_TRANSPARENT BIT( 2 ) // transparent texture
#define MIPTEX_RENDERMODE BIT( 3 ) // this surface requires a rendermode stuff
#define MIPTEX_NOLIGHTMAP BIT( 4 ) // this surface if fullbright
#define MIPTEX_WARPSURFACE BIT( 5 ) // this surface is warped
typedef struct mtexinfo_s
{
float vecs[2][4];
short texturenum; // number in cached.textures
short width;
short height;
} mtexinfo_t;
typedef struct msurface_s
{
int visframe; // should be drawn when node is crossed
int flags; // see SURF_ for details
int contents;
int firstedge; // look up in model->edges[]. negative
int numedges; // numbers are backwards edges
short textureMins[2];
short extents[2];
mtexinfo_t *texinfo;
ref_shader_t *shader;
mesh_t *mesh;
mfog_t *fog;
decal_t *pdecals; // linked surface decals
mplane_t *plane;
union
{
float origin[3];
float mins[3];
};
union
{
float maxs[3];
float color[3];
};
// lighting info
int lmWidth;
int lmHeight;
int lmS;
int lmT;
int lmNum; // real lightmap texnum
byte *samples;
int numstyles;
byte styles[LM_STYLES];
float cached[LM_STYLES]; // values currently used in lightmap
int superLightStyle;
int fragmentframe; // for multi-check avoidance
} msurface_t;
#define CONTENTS_NODE 1 // fake contents to determine nodes
typedef struct mnode_s
{
// common with leaf
mplane_t *plane;
int pvsframe;
int contents; // for fast checking solid leafs
float mins[3];
float maxs[3]; // for bounding box culling
struct mnode_s *parent;
// node specific
struct mnode_s *children[2];
msurface_t *firstface; // used for grab lighting info, decals etc
uint numfaces;
} mnode_t;
typedef struct mleaf_s
{
// common with node
mplane_t *plane;
int pvsframe;
int contents;
float mins[3];
float maxs[3]; // for bounding box culling
struct mnode_s *parent;
// leaf specific
byte *compressed_vis;
int visframe;
msurface_t **firstMarkSurface;
int numMarkSurfaces;
} mleaf_t;
typedef struct
{
byte ambient[LM_STYLES][3];
byte diffuse[LM_STYLES][3];
byte styles[LM_STYLES];
byte direction[2];
} mgridlight_t;
typedef struct
{
int texNum;
float texMatrix[2][2];
} mlightmapRect_t;
typedef struct
{
int numsubmodels;
mmodel_t *submodels;
int nummodelsurfaces;
msurface_t *firstmodelsurface;
mnode_t *firstmodelnode; // used for lighting bmodels
int numplanes;
mplane_t *planes;
int numleafs; // number of visible leafs, not counting 0
mleaf_t *leafs;
int numnodes;
mnode_t *nodes;
int numsurfaces;
msurface_t *surfaces;
msurface_t **marksurfaces;
int numgridpoints;
mgridlight_t *lightgrid;
int numtexinfo;
mtexinfo_t *texinfo;
byte *visdata; // compressed visdata
byte *lightdata;
int numfogs;
mfog_t *fogs;
mfog_t *globalfog;
vec3_t gridSize;
vec3_t gridMins;
int gridBounds[4];
} mbrushmodel_t;
/*
==============================================================================
STUDIO MODELS
==============================================================================
*/
typedef struct
{
studiohdr_t *phdr;
studiohdr_t *thdr;
void *submodels;
int numsubmodels;
vec3_t *m_pSVectors; // UNDONE: calc SVectors on loading, simple transform on rendering
} mstudiodata_t;
/*
==============================================================================
SPRITE MODELS
==============================================================================
*/
//
// in memory representation
//
typedef struct mspriteframe_s
{
int width;
int height;
float up, down, left, right;
float radius;
shader_t shader;
} mspriteframe_t;
typedef struct
{
int numframes;
float *intervals;
mspriteframe_t *frames[1];
} mspritegroup_t;
typedef struct
{
frametype_t type;
mspriteframe_t *frameptr;
} mspriteframedesc_t;
typedef struct
{
int type;
int rendermode;
int numframes;
mspriteframedesc_t frames[1];
} msprite_t;
//===================================================================
//
// Whole model
//
typedef struct ref_model_s
{
char *name;
modtype_t type;
int touchFrame; // registration sequence
// volume occupied by the model graphics
vec3_t mins, maxs;
float radius;
int flags; // effect flags
// memory representation pointer
byte *mempool;
void *extradata;
// shader pointers for refresh registration_sequence
int numshaders;
ref_shader_t **shaders;
} ref_model_t;
//============================================================================
void R_InitModels( void );
void R_ShutdownModels( void );
void Mod_ClearAll( void );
ref_model_t *Mod_ForName( const char *name, qboolean crash );
mleaf_t *Mod_PointInLeaf( const vec3_t p, ref_model_t *model );
byte *Mod_LeafPVS( mleaf_t *leaf, ref_model_t *model );
uint Mod_Handle( ref_model_t *mod );
ref_model_t *Mod_ForHandle( unsigned int elem );
ref_model_t *R_RegisterModel( const char *name );
void R_BeginRegistration( const char *model );
void R_EndRegistration( const char *skyname );
texture_t *Mod_LoadTexture( struct mip_s *mt );
#define Mod_Malloc( mod, size ) Mem_Alloc(( mod )->mempool, size )
#define Mod_Realloc( mod, data, size ) Mem_Realloc(( mod )->mempool, data, size )
#define Mod_Free( data ) Mem_Free( data )
void Mod_Modellist_f( void );
#endif // R_MODEL_H

View File

@ -1,713 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// r_opengl.c - openg32.dll handler
//=======================================================================
#include "r_local.h"
glwstate_t glw_state;
#define MAX_PFDS 256
#define num_vidmodes ((int)(sizeof(vidmode) / sizeof(vidmode[0])) - 1)
#define WINDOW_STYLE (WS_OVERLAPPED|WS_BORDER|WS_SYSMENU|WS_CAPTION|WS_VISIBLE)
#define WINDOW_EX_STYLE (0)
#define GL_DRIVER_OPENGL "OpenGL32"
typedef enum
{
rserr_ok,
rserr_invalid_fullscreen,
rserr_invalid_mode,
rserr_unknown
} rserr_t;
typedef struct vidmode_s
{
const char *desc;
int width;
int height;
qboolean wideScreen;
} vidmode_t;
vidmode_t vidmode[] =
{
{"Mode 0: 4x3", 400, 300, false },
{"Mode 1: 4x3", 512, 384, false },
{"Mode 2: 4x3", 640, 480, false },
{"Mode 3: 4x3", 800, 600, false },
{"Mode 4: 4x3", 960, 720, false },
{"Mode 5: 4x3", 1024, 768, false },
{"Mode 6: 4x3", 1152, 864, false },
{"Mode 7: 4x3", 1280, 800, false },
{"Mode 8: 4x3", 1280, 960, false },
{"Mode 9: 4x3", 1280, 1024, false },
{"Mode 10: 4x3", 1600, 1200, false },
{"Mode 11: 4x3", 2048, 1536, false },
{"Mode 12: 16x9", 856, 480, true },
{"Mode 13: 16x9", 1024, 576, true },
{"Mode 14: 16x9", 1280, 720, true },
{"Mode 15: 16x9", 1360, 768, true },
{"Mode 16: 16x9", 1440, 900, true },
{"Mode 17: 16x9", 1680, 1050, true },
{"Mode 18: 16x9", 1920, 1200, true },
{"Mode 19: 16x9", 2560, 1600, true },
{NULL, 0, 0, 0 },
};
static dllfunc_t wgl_funcs[] =
{
{"wglChoosePixelFormat", (void **) &pwglChoosePixelFormat},
{"wglDescribePixelFormat", (void **) &pwglDescribePixelFormat},
// {"wglGetPixelFormat", (void **) &pwglGetPixelFormat},
{"wglSetPixelFormat", (void **) &pwglSetPixelFormat},
{"wglSwapBuffers", (void **) &pwglSwapBuffers},
{"wglCreateContext", (void **) &pwglCreateContext},
{"wglDeleteContext", (void **) &pwglDeleteContext},
{"wglGetProcAddress", (void **) &pwglGetProcAddress},
{"wglMakeCurrent", (void **) &pwglMakeCurrent},
{"wglGetCurrentContext", (void **) &pwglGetCurrentContext},
{"wglGetCurrentDC", (void **) &pwglGetCurrentDC},
{NULL, NULL}
};
dll_info_t opengl_dll = { "opengl32.dll", wgl_funcs, NULL, NULL, NULL, true };
qboolean R_DeleteContext( void )
{
if( glw_state.hGLRC )
{
pwglDeleteContext( glw_state.hGLRC );
glw_state.hGLRC = NULL;
}
if( glw_state.hDC )
{
ReleaseDC( glw_state.hWnd, glw_state.hDC );
glw_state.hDC = NULL;
}
return false;
}
/*
=================
R_ChoosePFD
=================
*/
static int R_ChoosePFD( int colorBits, int depthBits, int stencilBits )
{
PIXELFORMATDESCRIPTOR PFDs[MAX_PFDS], *current, *selected;
int i, numPFDs, pixelFormat = 0;
uint flags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
MsgDev( D_NOTE, "R_ChoosePFD( %i, %i, %i )\n", colorBits, depthBits, stencilBits);
// Count PFDs
if( glw_state.minidriver )
numPFDs = pwglDescribePixelFormat( glw_state.hDC, 0, 0, NULL );
else numPFDs = DescribePixelFormat( glw_state.hDC, 0, 0, NULL );
if( numPFDs > MAX_PFDS )
{
MsgDev( D_NOTE, "too many PFDs returned (%i > %i), reduce it\n", numPFDs, MAX_PFDS );
numPFDs = MAX_PFDS;
}
else if( numPFDs < 1 )
{
MsgDev( D_ERROR, "R_ChoosePFD failed\n" );
return 0;
}
MsgDev( D_NOTE, "R_ChoosePFD: %i PFDs found\n", numPFDs );
// run through all the PFDs, looking for the best match
for( i = 1, current = PFDs; i <= numPFDs; i++, current++ )
{
if( glw_state.minidriver )
pwglDescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current );
else DescribePixelFormat( glw_state.hDC, i, sizeof( PIXELFORMATDESCRIPTOR ), current );
// check acceleration
if(( current->dwFlags & PFD_GENERIC_FORMAT ) && !r_allow_software->integer )
continue;
// check flags
if(( current->dwFlags & flags ) != flags )
continue;
// check pixel type
if( current->iPixelType != PFD_TYPE_RGBA )
continue;
// check color bits
if( current->cColorBits < colorBits )
continue;
// check depth bits
if( current->cDepthBits < depthBits )
continue;
// check stencil bits
if( current->cStencilBits < stencilBits )
continue;
// if we don't have a selected PFD yet, then use it
if( !pixelFormat )
{
selected = current;
pixelFormat = i;
continue;
}
if( colorBits != selected->cColorBits )
{
if( colorBits == current->cColorBits || current->cColorBits > selected->cColorBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
if( depthBits != selected->cDepthBits )
{
if( depthBits == current->cDepthBits || current->cDepthBits > selected->cDepthBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
if( stencilBits != selected->cStencilBits )
{
if( stencilBits == current->cStencilBits || current->cStencilBits > selected->cStencilBits )
{
selected = current;
pixelFormat = i;
continue;
}
}
}
if( !pixelFormat )
{
MsgDev( D_ERROR, "R_ChoosePFD: no hardware acceleration found\n" );
return 0;
}
if( selected->dwFlags & PFD_GENERIC_FORMAT )
{
if( selected->dwFlags & PFD_GENERIC_ACCELERATED )
{
MsgDev( D_NOTE, "R_ChoosePFD:: MCD acceleration found\n" );
glw_state.software = false;
}
else
{
MsgDev( D_NOTE, "R_ChoosePFD: using software emulation\n" );
glw_state.software = true;
}
}
else
{
MsgDev( D_NOTE, "using hardware acceleration\n");
glw_state.software = false;
}
MsgDev( D_NOTE, "R_ChoosePFD: PIXELFORMAT %i selected\n", pixelFormat );
return pixelFormat;
}
qboolean R_SetPixelformat( void )
{
PIXELFORMATDESCRIPTOR PFD;
int colorBits, depthBits, stencilBits;
int pixelFormat;
size_t gamma_size;
byte *savedGamma;
Sys_LoadLibrary( NULL, &opengl_dll ); // load opengl32.dll
if( !opengl_dll.link ) return false;
glw_state.minidriver = false; // FIXME: allow 3dfx drivers too
if( glw_state.minidriver )
{
if(( glw_state.hDC = pwglGetCurrentDC()) == NULL )
return false;
}
else
{
if(( glw_state.hDC = GetDC( glw_state.hWnd )) == NULL )
return false;
}
// set color/depth/stencil
colorBits = (r_colorbits->integer) ? r_colorbits->integer : 32;
depthBits = (r_depthbits->integer) ? r_depthbits->integer : 24;
stencilBits = (r_stencilbits->integer) ? r_stencilbits->integer : 0;
// choose a pixel format
pixelFormat = R_ChoosePFD( colorBits, depthBits, stencilBits );
if( !pixelFormat )
{
// try again with default color/depth/stencil
if( colorBits > 16 || depthBits > 16 || stencilBits > 0 )
pixelFormat = R_ChoosePFD( 16, 16, 0 );
else pixelFormat = R_ChoosePFD( 32, 24, 0 );
if( !pixelFormat )
{
MsgDev( D_ERROR, "R_SetPixelformat: failed to find an appropriate PIXELFORMAT\n" );
ReleaseDC( glw_state.hWnd, glw_state.hDC );
glw_state.hDC = NULL;
return false;
}
}
// set the pixel format
if( glw_state.minidriver )
{
pwglDescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
if( !pwglSetPixelFormat( glw_state.hDC, pixelFormat, &PFD ))
{
MsgDev( D_ERROR, "R_SetPixelformat: wglSetPixelFormat failed\n" );
return R_DeleteContext();
}
}
else
{
DescribePixelFormat( glw_state.hDC, pixelFormat, sizeof( PIXELFORMATDESCRIPTOR ), &PFD );
if( !SetPixelFormat( glw_state.hDC, pixelFormat, &PFD ))
{
MsgDev( D_ERROR, "R_SetPixelformat: failed\n" );
return R_DeleteContext();
}
}
glConfig.color_bits = PFD.cColorBits;
glConfig.depth_bits = PFD.cDepthBits;
glConfig.stencil_bits = PFD.cStencilBits;
if(!(glw_state.hGLRC = pwglCreateContext( glw_state.hDC )))
return R_DeleteContext();
if(!(pwglMakeCurrent( glw_state.hDC, glw_state.hGLRC )))
return R_DeleteContext();
if( PFD.cStencilBits != 0 )
glState.stencilEnabled = true;
else glState.stencilEnabled = false;
// print out PFD specifics
MsgDev( D_NOTE, "GL PFD: color(%d-bits) Z(%d-bit)\n", ( int )PFD.cColorBits, ( int )PFD.cDepthBits );
// init gamma ramp
ZeroMemory( glState.stateRamp, sizeof(glState.stateRamp));
if( pwglGetDeviceGammaRamp3DFX )
glConfig.deviceSupportsGamma = pwglGetDeviceGammaRamp3DFX( glw_state.hDC, glState.stateRamp );
else glConfig.deviceSupportsGamma = GetDeviceGammaRamp( glw_state.hDC, glState.stateRamp );
// share this extension so engine can grab them
GL_SetExtension( R_HARDWARE_GAMMA_CONTROL, glConfig.deviceSupportsGamma );
savedGamma = FS_LoadFile( "gamma.dat", &gamma_size );
if( !savedGamma || gamma_size != sizeof( glState.stateRamp ))
{
// saved gamma not found or corrupted file
FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof(glState.stateRamp));
MsgDev( D_NOTE, "gamma.dat initialized\n" );
if( savedGamma ) Mem_Free( savedGamma );
}
else
{
GL_BuildGammaTable();
// validate base gamma
if( !memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp )))
{
// all ok, previous gamma is valid
MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - ok\n" );
}
else if( !memcmp( glState.gammaRamp, glState.stateRamp, sizeof( glState.stateRamp )))
{
// screen gamma is equal to render gamma (probably previous instance crashed)
// run additional check to make sure it
if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp )))
{
// yes, current gamma it's totally wrong, restore it from gamma.dat
MsgDev( D_NOTE, "R_SetPixelformat: restore original gamma after crash\n" );
Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp ));
}
else
{
// oops, savedGamma == glState.stateRamp == glState.gammaRamp
// probably r_gamma set as default
MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - disabled\n" );
}
}
else if( !memcmp( glState.gammaRamp, savedGamma, sizeof( glState.stateRamp )))
{
// saved gamma is equal render gamma, probably gamma.dat writed after crash
// run additional check to make sure it
if( memcmp( savedGamma, glState.stateRamp, sizeof( glState.stateRamp )))
{
// yes, saved gamma it's totally wrong, get origianl gamma from screen
MsgDev( D_NOTE, "R_SetPixelformat: merge gamma.dat after crash\n" );
FS_WriteFile( "gamma.dat", glState.stateRamp, sizeof( glState.stateRamp ));
}
else
{
// oops, savedGamma == glState.stateRamp == glState.gammaRamp
// probably r_gamma set as default
MsgDev( D_NOTE, "R_SetPixelformat: validate screen gamma - disabled\n" );
}
}
else
{
// current gamma unset by other application, we can restore it here
MsgDev( D_NOTE, "R_SetPixelformat: restore original gamma after crash\n" );
Mem_Copy( glState.stateRamp, savedGamma, sizeof( glState.gammaRamp ));
}
Mem_Free( savedGamma );
}
r_gamma->modified = true;
return true;
}
void R_RestoreGamma( void )
{
if( !glw_state.hDC ) return;
SetDeviceGammaRamp( glw_state.hDC, glState.stateRamp );
}
void R_Free_OpenGL( void )
{
R_RestoreGamma ();
if( pwglMakeCurrent ) pwglMakeCurrent( NULL, NULL );
if( glw_state.hGLRC )
{
if( pwglDeleteContext ) pwglDeleteContext( glw_state.hGLRC );
glw_state.hGLRC = NULL;
}
if( glw_state.hDC )
{
ReleaseDC( glw_state.hWnd, glw_state.hDC );
glw_state.hDC = NULL;
}
if( glw_state.hWnd )
{
DestroyWindow ( glw_state.hWnd );
glw_state.hWnd = NULL;
}
UnregisterClass( "Xash Window", glw_state.hInst );
if( glState.fullScreen )
{
ChangeDisplaySettings( 0, 0 );
glState.fullScreen = false;
}
Sys_FreeLibrary( &opengl_dll );
// now all extensions are disabled
Mem_Set( glConfig.extension, 0, sizeof( glConfig.extension[0] ) * R_EXTCOUNT );
glw_state.initialized = false;
}
void R_SaveVideoMode( int vid_mode )
{
int mode = bound( 0, vid_mode, num_vidmodes ); // check range
glState.width = vidmode[mode].width;
glState.height = vidmode[mode].height;
glState.wideScreen = vidmode[mode].wideScreen;
Cvar_FullSet( "width", va( "%i", vidmode[mode].width ), CVAR_READ_ONLY );
Cvar_FullSet( "height", va( "%i", vidmode[mode].height ), CVAR_READ_ONLY );
Cvar_SetFloat( "r_mode", mode ); // merge if it out of bounds
MsgDev( D_NOTE, "Set: %s [%dx%d]\n", vidmode[mode].desc, vidmode[mode].width, vidmode[mode].height );
}
qboolean R_CreateWindow( int width, int height, qboolean fullscreen )
{
WNDCLASS wc;
RECT rect;
convar_t *r_xpos, *r_ypos;
int x = 0, y = 0, w, h;
int stylebits = WINDOW_STYLE;
int exstyle = WINDOW_EX_STYLE;
static string wndname;
com.snprintf( wndname, sizeof( wndname ), "%s", GI->title );
// register the frame class
wc.style = CS_OWNDC|CS_NOCLOSE;
wc.lpfnWndProc = (WNDPROC)glw_state.wndproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = glw_state.hInst;
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (void *)COLOR_3DSHADOW;
wc.lpszClassName = "Xash Window";
wc.lpszMenuName = 0;
// find the icon file in the filesystem
if( FS_FileExistsEx( "game.ico", true ))
{
char localPath[MAX_PATH];
com.snprintf( localPath, sizeof( localPath ), "%s/game.ico", GI->gamedir );
wc.hIcon = LoadImage( NULL, localPath, IMAGE_ICON, 0, 0, LR_LOADFROMFILE|LR_DEFAULTSIZE );
if( !wc.hIcon )
{
MsgDev( D_INFO, "Extract game.ico from pak if you want to see it.\n" );
wc.hIcon = LoadIcon( glw_state.hInst, MAKEINTRESOURCE( 101 ));
}
}
else wc.hIcon = LoadIcon( glw_state.hInst, MAKEINTRESOURCE( 101 ));
if( !RegisterClass( &wc ))
{
MsgDev( D_ERROR, "R_CreateWindow: couldn't register window class %s\n" "Xash Window" );
return false;
}
if( fullscreen )
{
stylebits = WS_POPUP|WS_VISIBLE;
exstyle = WS_EX_TOPMOST;
}
rect.left = 0;
rect.top = 0;
rect.right = width;
rect.bottom = height;
AdjustWindowRect( &rect, stylebits, FALSE );
w = rect.right - rect.left;
h = rect.bottom - rect.top;
if( !fullscreen )
{
r_xpos = Cvar_Get( "r_xpos", "130", CVAR_RENDERINFO, "window position by horizontal" );
r_ypos = Cvar_Get( "r_ypos", "48", CVAR_RENDERINFO, "window position by vertical" );
x = r_xpos->integer;
y = r_ypos->integer;
// adjust window coordinates if necessary
// so that the window is completely on screen
if( x < 0 ) x = 0;
if( y < 0 ) y = 0;
if( Cvar_VariableInteger( "r_mode" ) != glConfig.prev_mode )
{
if(( x + w > glw_state.desktopWidth ) || ( y + h > glw_state.desktopHeight ))
{
x = ( glw_state.desktopWidth - w ) / 2;
y = ( glw_state.desktopHeight - h ) / 2;
}
}
}
glw_state.hWnd = CreateWindowEx( exstyle, "Xash Window", wndname, stylebits, x, y, w, h, NULL, NULL, glw_state.hInst, NULL );
if( !glw_state.hWnd )
{
MsgDev( D_ERROR, "R_CreateWindow: couldn't create '%s'\n", wndname );
return false;
}
ShowWindow( glw_state.hWnd, SW_SHOW );
UpdateWindow( glw_state.hWnd );
// init all the gl stuff for the window
if( !R_SetPixelformat( ))
{
ShowWindow( glw_state.hWnd, SW_HIDE );
DestroyWindow( glw_state.hWnd );
glw_state.hWnd = NULL;
UnregisterClass( "Xash Window", glw_state.hInst );
MsgDev( D_ERROR, "OpenGL driver not installed\n" );
return false;
}
SetForegroundWindow( glw_state.hWnd );
SetFocus( glw_state.hWnd );
return true;
}
rserr_t R_ChangeDisplaySettings( int vid_mode, qboolean fullscreen )
{
int width, height;
HDC hDC;
R_SaveVideoMode( vid_mode );
width = r_width->integer;
height = r_height->integer;
// check our desktop attributes
hDC = GetDC( GetDesktopWindow() );
glw_state.desktopBitsPixel = GetDeviceCaps( hDC, BITSPIXEL );
glw_state.desktopWidth = GetDeviceCaps( hDC, HORZRES );
glw_state.desktopHeight = GetDeviceCaps( hDC, VERTRES );
ReleaseDC( GetDesktopWindow(), hDC );
// destroy the existing window
if( glw_state.hWnd ) R_Free_OpenGL();
// do a CDS if needed
if( fullscreen )
{
DEVMODE dm;
ZeroMemory( &dm, sizeof( dm ));
dm.dmSize = sizeof( dm );
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
if( vid_displayfrequency->integer > 0 )
{
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = vid_displayfrequency->integer;
}
if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) == DISP_CHANGE_SUCCESSFUL )
{
glState.fullScreen = true;
if( !R_CreateWindow( width, height, true ))
return rserr_invalid_mode;
return rserr_ok;
}
else
{
dm.dmPelsWidth = width * 2;
dm.dmPelsHeight = height;
dm.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT;
if( r_depthbits->integer != 0 )
{
dm.dmBitsPerPel = r_depthbits->integer;
dm.dmFields |= DM_BITSPERPEL;
}
// our first CDS failed, so maybe we're running on some weird dual monitor system
if( ChangeDisplaySettings( &dm, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
{
ChangeDisplaySettings( 0, 0 );
glState.fullScreen = false;
if( !R_CreateWindow( width, height, false ))
return rserr_invalid_mode;
return rserr_invalid_fullscreen;
}
else
{
if( !R_CreateWindow( width, height, true ))
return rserr_invalid_mode;
glState.fullScreen = true;
return rserr_ok;
}
}
}
else
{
ChangeDisplaySettings( 0, 0 );
glState.fullScreen = false;
if( !R_CreateWindow( width, height, false ))
return rserr_invalid_mode;
}
return rserr_ok;
}
/*
==================
R_Init_OpenGL
==================
*/
qboolean R_Init_OpenGL( void )
{
rserr_t err;
qboolean fullscreen;
fullscreen = vid_fullscreen->integer;
vid_fullscreen->modified = false;
r_mode->modified = false;
if(( err = R_ChangeDisplaySettings( r_mode->integer, fullscreen )) == rserr_ok )
{
glConfig.prev_mode = r_mode->integer;
}
else
{
if( err == rserr_invalid_fullscreen )
{
Cvar_SetFloat( "fullscreen", 0 );
vid_fullscreen->modified = false;
MsgDev( D_ERROR, "R_SetMode: fullscreen unavailable in this mode\n" );
if(( err = R_ChangeDisplaySettings( r_mode->integer, false )) == rserr_ok )
return true;
}
else if( err == rserr_invalid_mode )
{
Cvar_SetFloat( "r_mode", glConfig.prev_mode );
r_mode->modified = false;
MsgDev( D_ERROR, "R_SetMode: invalid mode\n" );
}
// try setting it back to something safe
if(( err = R_ChangeDisplaySettings( glConfig.prev_mode, false )) != rserr_ok )
{
MsgDev( D_ERROR, "R_SetMode: could not revert to safe mode\n" );
return false;
}
}
return true;
}
/*
=================
R_CheckForErrors
=================
*/
void R_CheckForErrors_( const char *filename, const int fileline )
{
int err;
char *str;
if( !r_check_errors->integer )
return;
if((err = pglGetError()) == GL_NO_ERROR )
return;
switch( err )
{
case GL_STACK_OVERFLOW:
str = "GL_STACK_OVERFLOW";
break;
case GL_STACK_UNDERFLOW:
str = "GL_STACK_UNDERFLOW";
break;
case GL_INVALID_ENUM:
str = "GL_INVALID_ENUM";
break;
case GL_INVALID_VALUE:
str = "GL_INVALID_VALUE";
break;
case GL_INVALID_OPERATION:
str = "GL_INVALID_OPERATION";
break;
case GL_OUT_OF_MEMORY:
str = "GL_OUT_OF_MEMORY";
break;
default:
str = "UNKNOWN ERROR";
break;
}
Host_Error( "R_CheckForErrors: %s (called at %s:%i)\n", str, filename, fileline );
}

File diff suppressed because it is too large Load Diff

View File

@ -1,456 +0,0 @@
/*
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.
*/
// r_poly.c - handles fragments and arbitrary polygons
#include "r_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
static mesh_t poly_mesh;
/*
=================
R_PushPoly
=================
*/
void R_PushPoly( const meshbuffer_t *mb )
{
poly_t *p;
ref_shader_t *shader;
int i, j, features;
MB_NUM2SHADER( mb->shaderkey, shader );
features = ( shader->features|MF_TRIFAN );
for( i = -mb->infokey-1, p = r_polys + i; i < mb->lastPoly; i++, p++ )
{
poly_mesh.numVerts = p->numverts;
poly_mesh.vertexArray = inVertsArray;
poly_mesh.normalsArray = inNormalsArray;
poly_mesh.stCoordArray = p->stcoords;
poly_mesh.colorsArray = p->colors;
for( j = 0; j < p->numverts; j++ )
{
Vector4Set( inVertsArray[r_backacc.numVerts+j], p->verts[j][0], p->verts[j][1], p->verts[j][2], 1 );
VectorCopy( p->normal, inNormalsArray[r_backacc.numVerts+j] );
}
R_PushMesh( &poly_mesh, features );
}
}
/*
=================
R_AddPolysToList
=================
*/
void R_AddPolysToList( void )
{
uint i, nverts = 0;
int fognum = -1;
mfog_t *fog, *lastFog = NULL;
meshbuffer_t *mb = NULL;
ref_shader_t *shader;
vec3_t lastNormal = { 0, 0, 0 };
poly_t *p;
RI.currententity = r_worldent;
for( i = 0, p = r_polys; i < r_numPolys; nverts += p->numverts, mb->lastPoly++, i++, p++ )
{
shader = p->shader;
if( p->fognum < 0 ) fognum = -1;
else if( p->fognum ) fognum = bound( 1, p->fognum, r_worldbrushmodel->numfogs + 1 );
else fognum = r_worldbrushmodel->numfogs ? 0 : -1;
if( fognum == -1 ) fog = NULL;
else if( !fognum ) fog = R_FogForSphere( p->verts[0], 0 );
else fog = r_worldbrushmodel->fogs + fognum - 1;
// we ignore SHADER_ENTITY_MERGABLE here because polys are just regular trifans
if( !mb || mb->shaderkey != (int)shader->sortkey
|| lastFog != fog || nverts + p->numverts > MAX_ARRAY_VERTS
|| (( shader->flags & SHADER_MATERIAL ) && !VectorCompare( p->normal, lastNormal )))
{
nverts = 0;
lastFog = fog;
VectorCopy( p->normal, lastNormal );
mb = R_AddMeshToList( MB_POLY, fog, shader, -( (signed int)i+1 ) );
mb->lastPoly = i;
}
}
}
//==================================================================================
static int r_fragmentframecount;
static vec3_t trace_start, trace_end;
static vec3_t trace_absmins, trace_absmaxs;
static float trace_fraction;
static vec3_t trace_impact;
static mplane_t trace_plane;
static msurface_t *trace_surface;
static int trace_hitbox;
/*
=================
R_TraceAgainstTriangle
Ray-triangle intersection as per
http://geometryalgorithms.com/Archive/algorithm_0105/algorithm_0105.htm
(original paper by Dan Sunday)
=================
*/
static void R_TraceAgainstTriangle( const vec_t *a, const vec_t *b, const vec_t *c )
{
const vec_t *p1 = trace_start, *p2 = trace_end, *p0 = a;
vec3_t u, v, w, n, p;
float d1, d2, d, frac;
float uu, uv, vv, wu, wv, s, t;
// calculate two mostly perpendicular edge directions
VectorSubtract( b, p0, u );
VectorSubtract( c, p0, v );
// we have two edge directions, we can calculate the normal
CrossProduct( v, u, n );
if( VectorCompare( n, vec3_origin ) )
return; // degenerate triangle
VectorSubtract( p2, p1, p );
VectorSubtract( p1, p0, w );
d1 = -DotProduct( n, w );
d2 = DotProduct( n, p );
if( fabs( d2 ) < 0.0001 )
return;
// get intersect point of ray with triangle plane
frac = (d1) / d2;
if( frac <= 0 ) return;
if( frac >= trace_fraction )
return; // we have hit something earlier
// calculate the impact point
VectorLerp( p1, frac, p2, p );
// does p lie inside triangle?
uu = DotProduct( u, u );
uv = DotProduct( u, v );
vv = DotProduct( v, v );
VectorSubtract( p, p0, w );
wu = DotProduct( w, u );
wv = DotProduct( w, v );
d = uv * uv - uu * vv;
// get and test parametric coords
s = (uv * wv - vv * wu) / d;
if( s < 0.0 || s > 1.0 )
return; // p is outside
t = (uv * wu - uu * wv) / d;
if( t < 0.0 || (s + t) > 1.0 )
return; // p is outside
trace_fraction = frac;
VectorCopy( p, trace_impact );
VectorCopy( n, trace_plane.normal );
}
/*
=================
R_TraceAgainstSurface
=================
*/
static qboolean R_TraceAgainstSurface( msurface_t *surf )
{
int i;
mesh_t *mesh;
elem_t *elem;
vec4_t *verts;
float old_frac = trace_fraction;
if( !surf ) return false;
mesh = surf->mesh;
if( !mesh ) return false;
elem = mesh->elems;
if( !elem ) return false;
verts = mesh->vertexArray;
if( !verts ) return false;
// clip each triangle individually
for( i = 0; i < mesh->numElems; i += 3, elem += 3 )
{
R_TraceAgainstTriangle( verts[elem[0]], verts[elem[1]], verts[elem[2]] );
if( old_frac > trace_fraction )
{
// flip normal is we are on the backside (does it really happen?)...
if( DotProduct( trace_plane.normal, surf->plane->normal ) < 0 )
VectorNegate( trace_plane.normal, trace_plane.normal );
return true;
}
}
return false;
}
/*
=================
R_TraceAgainstLeaf
=================
*/
static int R_TraceAgainstLeaf( mleaf_t *leaf )
{
msurface_t *surf, **mark;
int i;
if( leaf->contents == CONTENTS_SOLID )
return 1; // solid leaf
mark = leaf->firstMarkSurface;
for( i = 0, mark = leaf->firstMarkSurface; i < leaf->numMarkSurfaces; i++, mark++ )
{
surf = *mark;
if( surf->fragmentframe == r_fragmentframecount )
continue; // do not test the same surface more than once
surf->fragmentframe = r_fragmentframecount;
if( surf->mesh )
{
if( R_TraceAgainstSurface( surf ) )
trace_surface = surf; // impact surface
}
}
return 0;
}
/*
=================
R_TraceAgainstBmodel
=================
*/
static int R_TraceAgainstBmodel( mbrushmodel_t *bmodel )
{
int i;
msurface_t *surf;
for( i = 0; i < bmodel->nummodelsurfaces; i++ )
{
surf = bmodel->firstmodelsurface + i;
if( R_TraceAgainstSurface( surf ) )
trace_surface = surf; // impact point
}
return 0;
}
/*
=================
R_RecursiveHullCheck
=================
*/
static int R_RecursiveHullCheck( mnode_t *node, const vec3_t start, const vec3_t end )
{
int side, r;
float t1, t2;
float frac;
vec3_t mid;
const vec_t *p1 = start, *p2 = end;
mplane_t *plane;
loc0:
plane = node->plane;
if( !plane )
return R_TraceAgainstLeaf( ( mleaf_t * )node );
if( plane->type < 3 )
{
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
}
else
{
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
}
if( t1 >= -ON_EPSILON && t2 >= -ON_EPSILON )
{
node = node->children[0];
goto loc0;
}
if( t1 < ON_EPSILON && t2 < ON_EPSILON )
{
node = node->children[1];
goto loc0;
}
side = t1 < 0;
frac = t1 / (t1 - t2);
VectorLerp( p1, frac, p2, mid );
r = R_RecursiveHullCheck( node->children[side], p1, mid );
if( r )
return r;
return R_RecursiveHullCheck( node->children[!side], mid, p2 );
}
/*
=================
R_TraceLine
=================
*/
msurface_t *R_TransformedTraceLine( pmtrace_t *tr, const vec3_t start, const vec3_t end, ref_entity_t *test, int flags )
{
ref_model_t *model;
r_fragmentframecount++; // for multi-check avoidance
// fill in a default trace
Mem_Set( tr, 0, sizeof( pmtrace_t ));
trace_hitbox = -1;
trace_surface = NULL;
trace_fraction = 1.0f;
VectorCopy( end, trace_impact );
Mem_Set( &trace_plane, 0, sizeof( trace_plane ));
// skip glass ents
if(( flags & FTRACE_IGNORE_GLASS ) && test->rendermode != kRenderNormal && test->renderamt < 200 )
{
tr->fraction = trace_fraction;
VectorCopy( trace_impact, tr->endpos );
return trace_surface;
}
ClearBounds( trace_absmins, trace_absmaxs );
AddPointToBounds( start, trace_absmins, trace_absmaxs );
AddPointToBounds( end, trace_absmins, trace_absmaxs );
model = test->model;
if( model )
{
if( model->type == mod_world || model->type == mod_brush || model->type == mod_studio )
{
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
qboolean rotated = !Matrix3x3_Compare( test->axis, matrix3x3_identity );
vec3_t temp, start_l, end_l, axis[3];
vec3_t model_mins, model_maxs;
float v, max = 0.0f;
int i;
// transform
VectorSubtract( start, test->origin, start_l );
VectorSubtract( end, test->origin, end_l );
if( rotated )
{
VectorCopy( start_l, temp );
Matrix3x3_Transform( test->axis, temp, start_l );
VectorCopy( end_l, temp );
Matrix3x3_Transform( test->axis, temp, end_l );
// expand mins/maxs for rotation
for( i = 0; i < 3; i++ )
{
v = fabs( model->mins[i] );
if( v > max ) max = v;
v = fabs( model->maxs[i] );
if( v > max ) max = v;
}
for( i = 0; i < 3; i++ )
{
model_mins[i] = test->origin[i] - max;
model_maxs[i] = test->origin[i] + max;
}
}
else
{
VectorAdd( test->origin, model->mins, model_mins );
VectorAdd( test->origin, model->maxs, model_maxs );
}
VectorCopy( start_l, trace_start );
VectorCopy( end_l, trace_end );
// world uses a recursive approach using BSP tree, submodels
// just walk the list of surfaces linearly
if( model->type == mod_world )
R_RecursiveHullCheck( bmodel->nodes, start_l, end_l );
else if( BoundsIntersect( model_mins, model_maxs, trace_absmins, trace_absmaxs ))
{
if( model->type == mod_brush )
R_TraceAgainstBmodel( bmodel );
else if( model->type == mod_studio )
{
pmtrace_t tr;
if( R_StudioTrace( test, trace_start, trace_end, &tr ))
{
VectorCopy( tr.endpos, trace_impact );
VectorCopy( tr.plane.normal, trace_plane.normal );
trace_fraction = tr.fraction;
trace_hitbox = tr.hitgroup;
}
}
}
// transform back
if( rotated && trace_fraction != 1 )
{
Matrix3x3_Transpose( axis, test->axis );
VectorCopy( tr->plane.normal, temp );
Matrix3x3_Transform( axis, temp, trace_plane.normal );
}
}
}
// calculate the impact plane, if any
if( trace_fraction < 1.0f )
{
VectorNormalize( trace_plane.normal );
trace_plane.dist = DotProduct( trace_plane.normal, trace_impact );
CategorizePlane( &trace_plane );
tr->plane.dist = trace_plane.dist;
VectorCopy( trace_plane.normal, tr->plane.normal );
tr->ent = test - r_entities;
}
tr->hitgroup = trace_hitbox;
tr->fraction = trace_fraction;
VectorCopy( trace_impact, tr->endpos );
return trace_surface;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,359 +0,0 @@
/*
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.
*/
#ifndef R_SHADER_H
#define R_SHADER_H
#define MAX_SHADERS 4096
#define SHADERS_HASH_SIZE 256
#define MAX_STAGE_TEXTURES 256 // same as MAX_SPRITE_FRAMES
#define MAX_SHADER_STAGES 8
#define MAX_SHADER_DEFORMS 8
#define MAX_SHADER_TCMODS 8
#define MAX_TABLES 4096
#define TABLES_HASH_SIZE 1024
// shader types
#define SHADER_INVALID -1
#define SHADER_UNKNOWN 0
#define SHADER_SKY 1
#define SHADER_NOMIP 2
#define SHADER_DECAL 3
#define SHADER_SPRITE 4
#define SHADER_GENERIC 5
#define SHADER_TEXTURE 6
#define SHADER_FLARE 7
#define SHADER_STUDIO 8
#define SHADER_FARBOX 9
#define SHADER_NEARBOX 10
#define SHADER_PLANAR_SHADOW 11
#define SHADER_OPAQUE_OCCLUDER 12
// shader flags
typedef enum
{
SHADER_STATIC = BIT(0), // never freed by R_ShaderFreeUnused
SHADER_DEPTHWRITE = BIT(1),
SHADER_SKYPARMS = BIT(2),
SHADER_DECALPARMS = BIT(3), // it's a lightmapped decal
SHADER_POLYGONOFFSET = BIT(4),
SHADER_CULL_FRONT = BIT(5),
SHADER_CULL_BACK = BIT(6),
SHADER_DEFAULTED = BIT(7),
SHADER_MATERIAL = BIT(8),
SHADER_DEFORM_NORMAL = BIT(9),
SHADER_ENTITY_MERGABLE = BIT(10),
SHADER_AUTOSPRITE = BIT(11),
SHADER_NO_MODULATIVE_DLIGHTS = BIT(12),
SHADER_HASLIGHTMAP = BIT(13),
SHADER_PORTAL = BIT(14),
SHADER_PORTAL_CAPTURE1 = BIT(15),
SHADER_PORTAL_CAPTURE2 = BIT(16),
SHADER_RENDERMODE = BIT(17),
SHADER_PORTAL_CAPTURE = (SHADER_PORTAL_CAPTURE1|SHADER_PORTAL_CAPTURE1),
SHADER_CULL = (SHADER_CULL_FRONT|SHADER_CULL_BACK),
} shaderFlags_t;
// shaderstage flags
enum
{
SHADERSTAGE_ANIMFREQUENCY = BIT(0), // auto-animate value
SHADERSTAGE_FRAMES = BIT(1), // bundle have anim frames, thats can be switching manually
SHADERSTAGE_ANGLEDMAP = BIT(2), // doom1 eight angle-aligned ( 360 / 8 ) textures
SHADERSTAGE_LIGHTMAP = BIT(3),
SHADERSTAGE_DETAIL = BIT(4),
SHADERSTAGE_NOCOLORARRAY = BIT(5),
SHADERSTAGE_DLIGHT = BIT(6),
SHADERSTAGE_PORTALMAP = BIT(7),
SHADERSTAGE_STENCILSHADOW = BIT(8),
SHADERSTAGE_RENDERMODE = BIT(9),
SHADERSTAGE_BLEND_REPLACE = BIT(10),
SHADERSTAGE_BLEND_MODULATE = BIT(11),
SHADERSTAGE_BLEND_ADD = BIT(12),
SHADERSTAGE_BLEND_DECAL = BIT(13)
} stageFlags_t;
#define SHADERSTAGE_BLENDMODE (SHADERSTAGE_BLEND_REPLACE|SHADERSTAGE_BLEND_MODULATE|SHADERSTAGE_BLEND_ADD|SHADERSTAGE_BLEND_DECAL)
// sorting
typedef enum
{
SORT_NONE = 0,
SORT_PORTAL = 1,
SORT_SKY = 2,
SORT_OPAQUE = 3,
SORT_DECAL = 4,
SORT_ALPHATEST = 5,
SORT_BANNER = 6,
SORT_UNDERWATER = 7,
SORT_WATER = 8,
SORT_ADDITIVE = 9,
SORT_NEAREST = 16
} sort_t;
// transform functions
typedef enum
{
WAVEFORM_NONE = 0,
WAVEFORM_SIN,
WAVEFORM_TRIANGLE,
WAVEFORM_SQUARE,
WAVEFORM_SAWTOOTH,
WAVEFORM_INVERSESAWTOOTH,
WAVEFORM_NOISE,
WAVEFORM_CONSTANT,
WAVEFORM_TABLE // custom table
} waveForm_t;
// RGB colors generation
typedef enum
{
RGBGEN_UNKNOWN = 0,
RGBGEN_IDENTITY,
RGBGEN_IDENTITY_LIGHTING,
RGBGEN_CONST,
RGBGEN_WAVE,
RGBGEN_COLORWAVE,
RGBGEN_ENTITY,
RGBGEN_ONE_MINUS_ENTITY,
RGBGEN_VERTEX,
RGBGEN_ONE_MINUS_VERTEX,
RGBGEN_LIGHTING_DIFFUSE,
RGBGEN_LIGHTING_AMBIENT,
RGBGEN_EXACT_VERTEX,
RGBGEN_CUSTOM,
RGBGEN_FOG, // followed extensions only for internal use
RGBGEN_ENVIRONMENT
} rgbGenType_t;
// alpha channel generation
typedef enum
{
ALPHAGEN_UNKNOWN = 0,
ALPHAGEN_IDENTITY,
ALPHAGEN_CONST,
ALPHAGEN_PORTAL,
ALPHAGEN_VERTEX,
ALPHAGEN_ONE_MINUS_VERTEX,
ALPHAGEN_ENTITY,
ALPHAGEN_ONE_MINUS_ENTITY,
ALPHAGEN_SPECULAR,
ALPHAGEN_WAVE,
ALPHAGEN_ALPHAWAVE,
ALPHAGEN_FADE, // same as portal but for other things
ALPHAGEN_ONE_MINUS_FADE,
ALPHAGEN_DOT,
ALPHAGEN_ONE_MINUS_DOT,
} alphaGenType_t;
// texture coordinates generation
typedef enum
{
TCGEN_NONE = 0,
TCGEN_BASE,
TCGEN_LIGHTMAP,
TCGEN_ENVIRONMENT,
TCGEN_VECTOR,
TCGEN_WARP,
TCGEN_REFLECTION,
TCGEN_FOG,
TCGEN_REFLECTION_CELLSHADE,
TCGEN_SVECTORS,
TCGEN_PROJECTION,
TCGEN_PROJECTION_SHADOW,
TCGEN_NORMAL
} tcGenType_t;
// tcmod functions
typedef enum
{
TCMOD_NONE = 0,
TCMOD_TRANSLATE,
TCMOD_SCALE,
TCMOD_SCROLL,
TCMOD_ROTATE,
TCMOD_STRETCH,
TCMOD_TRANSFORM,
TCMOD_TURB,
TCMOD_CONVEYOR // same as TCMOD_SCROLL, but can be controlled by entity
} tcModType_t;
// vertices deformation
typedef enum
{
DEFORM_NONE = 0,
DEFORM_WAVE,
DEFORM_NORMAL,
DEFORM_BULGE,
DEFORM_MOVE,
DEFORM_AUTOSPRITE,
DEFORM_AUTOSPRITE2,
DEFORM_PROJECTION_SHADOW,
DEFORM_AUTOPARTICLE,
} deformType_t;
typedef enum
{
TABLE_SNAP = BIT(0),
TABLE_CLAMP = BIT(1)
} tableFlags_t;
typedef struct table_s
{
char *name; // table name
int index;
tableFlags_t flags;
int size;
float *values; // float[]
struct table_s *nextHash;
} table_t;
typedef struct
{
waveForm_t type; // SHADER_FUNC enum
uint tableIndex; // valid only for WAVEFORM_TABLE
float args[4]; // offset, amplitude, phase_offset, rate
} waveFunc_t;
typedef struct
{
tcModType_t type;
float args[6];
} tcMod_t;
typedef struct
{
rgbGenType_t type;
float *args;
waveFunc_t *func;
} rgbGen_t;
typedef struct
{
alphaGenType_t type;
float *args;
waveFunc_t *func;
} alphaGen_t;
typedef struct
{
deformType_t type;
float args[4];
waveFunc_t func;
} deform_t;
typedef struct old_stage_s
{
uint flags;
uint glState; // GLSTATE_ flags
rgbGen_t rgbGen;
alphaGen_t alphaGen;
} old_stage_t;
// Per-pass rendering state information
typedef struct ref_stage_s
{
uint flags;
uint glState; // GLSTATE_ flags
rgbGen_t rgbGen;
alphaGen_t alphaGen;
old_stage_t prev;
word tcgen;
vec_t *tcgenVec;
word numtcMods;
tcMod_t *tcMods;
const char *program;
word program_type;
float animFrequency[2]; // anim fps / alt anim fps
word anim_offset; // offset for alternative animation
word num_textures;
texture_t *textures[MAX_STAGE_TEXTURES]; // texture refs
} ref_stage_t;
// Shader information
typedef struct ref_shader_s
{
char *name;
word type;
shader_t shadernum; // 0 = free
uint flags;
word features;
sort_t sort;
sort_t realsort; // member original sort type until rendermode is reset
uint sortkey;
uint touchFrame; // 0 = free
word num_stages;
ref_stage_t *stages;
word numDeforms;
deform_t *deforms;
skydome_t *skyParms;
vec3_t skyAxis;
float skySpeed;
rgba_t fog_color;
float fog_dist;
float fog_clearDist;
float offsetmapping_scale;
float tessSize; // used for tcGen warp
struct ref_script_s *cache;
struct ref_shader_s *nextHash;
} ref_shader_t;
extern ref_shader_t r_shaders[MAX_SHADERS];
#define Shader_Sortkey( shader, sort ) ((( sort )<<26 )|( shader - r_shaders ))
void R_InitShaders( void );
void R_ShutdownShaders( void );
void R_ShaderList_f( void );
void R_ShaderDump_f( void );
ref_shader_t *R_FindShader( const char *name, int type, int ignoreType );
ref_shader_t *R_LoadShader( const char *name, int type, qboolean forceDefault, int addFlags, int ignoreType );
void Mod_FreeShader( const char *name ); // used for delete save menu previews only
// misc utilities
void R_ShaderFreeUnused( void );
float R_LookupTable( int tableIndex, float index );
float *R_GetTableByHandle( int tableIndex );
qboolean R_ShaderCheckCache( const char *name );
void R_SetInternalTexture( struct mip_s *mt );
void Shader_TouchImages( ref_shader_t *shader, qboolean free_unused );
void R_ShaderAddStageTexture( texture_t *mipTex );
void R_ShaderSetMiptexFlags( uint addFlags );
void R_ShaderSetRenderMode( int mode, qboolean twoSided );
void R_SetAnimFrequency( float anim_fps );
void R_ShaderAddStageIntervals( float interval );
void R_DeformvBBoxForShader( const ref_shader_t *shader, vec3_t ebbox );
#endif // R_SHADER_H

View File

@ -1,476 +0,0 @@
/*
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 "matrix_lib.h"
#include "cl_entity.h"
/*
=============================================================
PLANAR STENCIL SHADOWS
=============================================================
*/
static ref_shader_t *r_planarShadowShader;
/*
===============
R_InitPlanarShadows
===============
*/
static void R_InitPlanarShadows( void )
{
r_planarShadowShader = R_LoadShader( "***r_planarShadow***", SHADER_PLANAR_SHADOW, true, 0, 0 );
}
/*
===============
R_PlanarShadowShader
===============
*/
ref_shader_t *R_PlanarShadowShader( void )
{
return r_planarShadowShader;
}
/*
===============
R_GetShadowImpactAndDir
===============
*/
static void R_GetShadowImpactAndDir( ref_entity_t *e, pmtrace_t *tr, vec3_t lightdir )
{
vec3_t point;
R_LightDir( e->lightingOrigin, lightdir, e->model->radius * e->scale );
VectorSet( lightdir, -lightdir[0], -lightdir[1], -1 );
VectorNormalizeFast( lightdir );
VectorMA( e->origin, 1024.0f, lightdir, point );
R_TraceLine( tr, e->origin, point, 0 );
}
/*
===============
R_CullPlanarShadow
===============
*/
qboolean R_CullPlanarShadow( ref_entity_t *e, vec3_t mins, vec3_t maxs, qboolean occlusion_query )
{
float planedist, dist;
vec3_t lightdir, point;
vec3_t bbox[8], newmins, newmaxs;
pmtrace_t tr;
int i;
if(( e->flags & EF_NOSHADOW ) || ( e->ent_type == ET_VIEWENTITY ))
return true;
if( RP_LOCALCLIENT( e ))
return false;
R_GetShadowImpactAndDir( e, &tr, lightdir );
if( tr.fraction == 1.0f )
return true;
R_TransformEntityBBox( e, mins, maxs, bbox, true );
VectorSubtract( tr.endpos, e->origin, point );
planedist = DotProduct( point, tr.plane.normal ) + 1;
dist = -1.0f / DotProduct( lightdir, tr.plane.normal );
VectorScale( lightdir, dist, lightdir );
ClearBounds( newmins, newmaxs );
for( i = 0; i < 8; i++ )
{
VectorSubtract( bbox[i], e->origin, bbox[i] );
dist = DotProduct( bbox[i], tr.plane.normal ) - planedist;
if( dist > 0 ) VectorMA( bbox[i], dist, lightdir, bbox[i] );
AddPointToBounds( bbox[i], newmins, newmaxs );
}
VectorAdd( newmins, e->origin, newmins );
VectorAdd( newmaxs, e->origin, newmaxs );
if( R_CullBox( newmins, newmaxs, RI.clipFlags ))
return true;
// mins/maxs are pretransfomed so use r_worldent here
if( occlusion_query && OCCLUSION_QUERIES_ENABLED( RI ) )
R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_PLANARSHADOW, e - r_entities ), r_worldent, newmins, newmaxs );
return false;
}
/*
===============
R_DeformVPlanarShadow
===============
*/
void R_DeformVPlanarShadow( int numV, float *v )
{
float planedist, dist;
ref_entity_t *e = RI.currententity;
vec3_t planenormal, lightdir, lightdir2, point;
pmtrace_t tr;
R_GetShadowImpactAndDir( e, &tr, lightdir );
Matrix3x3_Transform( e->axis, lightdir, lightdir2 );
Matrix3x3_Transform( e->axis, tr.plane.normal, planenormal );
VectorScale( planenormal, e->scale, planenormal );
VectorSubtract( tr.endpos, e->origin, point );
planedist = DotProduct( point, tr.plane.normal ) + 1;
dist = -1.0f / DotProduct( lightdir2, planenormal );
VectorScale( lightdir2, dist, lightdir2 );
for( ; numV > 0; numV--, v += 4 )
{
dist = DotProduct( v, planenormal ) - planedist;
if( dist > 0 ) VectorMA( v, dist, lightdir2, v );
}
}
/*
===============
R_PlanarShadowPass
===============
*/
void R_PlanarShadowPass( int state )
{
GL_EnableTexGen( GL_S, 0 );
GL_EnableTexGen( GL_T, 0 );
GL_EnableTexGen( GL_R, 0 );
GL_EnableTexGen( GL_Q, 0 );
GL_SetTexCoordArrayMode( 0 );
GL_SetState( state );
pglColor4f( 0, 0, 0, bound( 0.0f, r_shadows_alpha->value, 1.0f ) );
pglDisable( GL_TEXTURE_2D );
if( glState.stencilEnabled )
pglEnable( GL_STENCIL_TEST );
R_FlushArrays();
if( glState.stencilEnabled )
pglDisable( GL_STENCIL_TEST );
pglEnable( GL_TEXTURE_2D );
}
/*
=============================================================
STANDARD PROJECTIVE SHADOW MAPS (SSM)
=============================================================
*/
int r_numShadowGroups;
shadowGroup_t r_shadowGroups[MAX_SHADOWGROUPS];
int r_entShadowBits[MAX_ENTITIES];
#define SHADOWGROUPS_HASH_SIZE 8
static shadowGroup_t *r_shadowGroups_hash[SHADOWGROUPS_HASH_SIZE];
static byte r_shadowCullBits[MAX_SHADOWGROUPS/8];
/*
===============
R_InitShadowmaps
===============
*/
static void R_InitShadowmaps( void )
{
// clear all possible values, should be called once per scene
r_numShadowGroups = 0;
Mem_Set( r_shadowGroups, 0, sizeof( r_shadowGroups ));
Mem_Set( r_entShadowBits, 0, sizeof( r_entShadowBits ));
Mem_Set( r_shadowGroups_hash, 0, sizeof( r_shadowGroups_hash ));
}
/*
===============
R_ClearShadowmaps
===============
*/
void R_ClearShadowmaps( void )
{
r_numShadowGroups = 0;
if( r_shadows->integer != SHADOW_MAPPING || !RI.drawWorld )
return;
// clear all possible values, should be called once per scene
Mem_Set( r_shadowGroups, 0, sizeof( r_shadowGroups ));
Mem_Set( r_entShadowBits, 0, sizeof( r_entShadowBits ));
Mem_Set( r_shadowGroups_hash, 0, sizeof( r_shadowGroups_hash ));
}
/*
===============
R_AddShadowCaster
===============
*/
qboolean R_AddShadowCaster( ref_entity_t *ent )
{
int i;
float radius;
vec3_t origin;
unsigned int hash_key;
shadowGroup_t *group;
mleaf_t *leaf;
vec3_t mins, maxs, bbox[8];
if( r_shadows->integer != SHADOW_MAPPING || !RI.drawWorld )
return false;
if( !GL_Support( R_SHADER_GLSL100_EXT ) || !GL_Support( R_DEPTH_TEXTURE ) || !GL_Support( R_SHADOW_EXT ))
return false;
VectorCopy( ent->lightingOrigin, origin );
if( VectorIsNull( origin ))
return false;
// find lighting group containing entities with same lightingOrigin as ours
hash_key = (uint)( origin[0] * 7 + origin[1] * 5 + origin[2] * 3 );
hash_key &= (SHADOWGROUPS_HASH_SIZE - 1);
for( group = r_shadowGroups_hash[hash_key]; group; group = group->hashNext )
{
if( VectorCompare( group->origin, origin ))
goto add; // found an existing one, add
}
if( r_numShadowGroups == MAX_SHADOWGROUPS )
return false; // no free groups
leaf = Mod_PointInLeaf( origin, r_worldmodel );
// start a new group
group = &r_shadowGroups[r_numShadowGroups];
group->bit = ( 1<<r_numShadowGroups );
group->vis = Mod_LeafPVS( leaf, r_worldmodel );
// clear group bounds
VectorCopy( origin, group->origin );
ClearBounds( group->mins, group->maxs );
// add to hash table
group->hashNext = r_shadowGroups_hash[hash_key];
r_shadowGroups_hash[hash_key] = group;
r_numShadowGroups++;
add:
// get model bounds
switch( ent->model->type )
{
case mod_studio:
R_StudioModelBBox( ent, mins, maxs );
break;
default:
VectorClear( mins );
VectorClear( maxs );
break;
}
for( i = 0; i < 3; i++ )
{
if( mins[i] >= maxs[i] )
return false;
}
r_entShadowBits[ent - r_entities] |= group->bit;
if( ent->ent_type == ET_VIEWENTITY )
return true;
// rotate local bounding box and compute the full bounding box for this group
R_TransformEntityBBox( ent, mins, maxs, bbox, true );
for( i = 0; i < 8; i++ )
AddPointToBounds( bbox[i], group->mins, group->maxs );
// increase projection distance if needed
VectorSubtract( group->mins, origin, mins );
VectorSubtract( group->maxs, origin, maxs );
radius = RadiusFromBounds( mins, maxs );
group->projDist = max( group->projDist, radius * ent->scale * 2 + min( r_shadows_projection_distance->value, 64 ));
return true;
}
/*
===============
R_CullShadowmapGroups
===============
*/
void R_CullShadowmapGroups( void )
{
int i, j;
vec3_t mins, maxs;
shadowGroup_t *group;
if( !RI.drawWorld ) return;
Mem_Set( r_shadowCullBits, 0, sizeof( r_shadowCullBits ));
for( i = 0, group = r_shadowGroups; i < r_numShadowGroups; i++, group++ )
{
for( j = 0; j < 3; j++ )
{
mins[j] = group->origin[j] - group->projDist * 1.75 * 0.5 * 0.5;
maxs[j] = group->origin[j] + group->projDist * 1.75 * 0.5 * 0.5;
}
// check if view point is inside the bounding box...
for( j = 0; j < 3; j++ )
{
if( RI.viewOrigin[j] < mins[j] || RI.viewOrigin[j] > maxs[j] )
break;
}
if( j == 3 ) continue; // ...it is, so trivially accept
if( R_CullBox( mins, maxs, RI.clipFlags ) )
r_shadowCullBits[i>>3] |= (1<<(i&7)); // trivially reject
else if( OCCLUSION_QUERIES_ENABLED( RI ))
R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_SHADOWGROUP, i ), r_worldent, mins, maxs );
}
}
/*
===============
R_DrawShadowmaps
===============
*/
void R_DrawShadowmaps( void )
{
int i, j;
int width, height, textureWidth, textureHeight;
vec3_t angles;
vec3_t lightdir, M[3];
refinst_t oldRI;
shadowGroup_t *group;
if( !r_numShadowGroups )
return;
width = r_lastRefdef.viewport[2];
height = r_lastRefdef.viewport[3];
RI.previousentity = NULL;
Mem_Copy( &oldRI, &prevRI, sizeof( refinst_t ));
Mem_Copy( &prevRI, &RI, sizeof( refinst_t ));
RI.rdflags &= ~RDF_SKYPORTALINVIEW;
// find lighting group containing entities with same lightingOrigin as ours
for( i = 0, group = r_shadowGroups; i < r_numShadowGroups; i++, group++ )
{
if( r_shadowCullBits[i>>3] & ( 1<<( i&7 ) ) )
continue;
if( OCCLUSION_QUERIES_ENABLED( prevRI ) )
{
if( !R_GetOcclusionQueryResultBool( OQ_SHADOWGROUP, i, true ) )
continue;
}
RI.farClip = group->projDist;
RI.clipFlags |= ( 1<<4 ); // clip by far plane too
RI.shadowBits = 0; // no shadowing yet
RI.meshlist = &r_shadowlist;
RI.shadowGroup = group;
RI.params = RP_SHADOWMAPVIEW|RP_FLIPFRONTFACE|RP_OLDVIEWLEAF; // make sure RP_WORLDSURFVISIBLE isn't set
// allocate/resize the texture if needed
R_InitShadowmapTexture( &( tr.shadowmapTextures[i] ), i, width, height );
group->depthTexture = tr.shadowmapTextures[i];
textureWidth = group->depthTexture->width;
textureHeight = group->depthTexture->height;
// default to fov 90, R_SetupFrame will most likely alter the values to give depth more precision
RI.refdef.viewport[2] = textureWidth;
RI.refdef.viewport[3] = textureHeight;
RI.refdef.fov_x = 90;
RI.refdef.fov_y = CalcFov( RI.refdef.fov_x, RI.refdef.viewport[2], RI.refdef.viewport[3] );
Vector4Set( RI.viewport, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight );
Vector4Set( RI.scissor, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight );
// set the view transformation matrix according to lightgrid
R_LightDir( group->origin, lightdir, group->projDist * 0.5f );
VectorSet( lightdir, -lightdir[0], -lightdir[1], -lightdir[2] );
VectorNormalizeFast( lightdir );
NormalVectorToAxis( lightdir, M );
Matrix3x3_ToAngles( M, angles, true );
for( j = 0; j < 3; j++ )
RI.refdef.viewangles[j] = anglemod( angles[j] );
// position the light source in the opposite direction
VectorMA( group->origin, -group->projDist * 0.5, lightdir, RI.refdef.vieworg );
R_RenderView( &RI.refdef );
if( !( RI.params & RP_WORLDSURFVISIBLE ) )
continue; // we didn't cast any shadows on opaque meshes so discard this group
if( !( prevRI.shadowBits & group->bit ))
{
// capture results from framebuffer into depth texture
prevRI.shadowBits |= group->bit;
GL_Bind( 0, group->depthTexture );
pglCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, RI.refdef.viewport[0], RI.refdef.viewport[1], textureWidth, textureHeight );
}
Matrix4x4_Copy( group->worldviewProjectionMatrix, RI.worldviewProjectionMatrix );
}
oldRI.shadowBits |= prevRI.shadowBits; // set shadowBits for all RI's so that we won't
Mem_Copy( &RI, &prevRI, sizeof( refinst_t ));
Mem_Copy( &prevRI, &oldRI, sizeof( refinst_t ));
}
//==================================================================================
/*
===============
R_InitShadows
===============
*/
void R_InitShadows( void )
{
R_InitPlanarShadows();
R_InitShadowmaps();
}
/*
===============
R_ShutdownShadows
===============
*/
void R_ShutdownShadows( void )
{
r_planarShadowShader = NULL;
}

View File

@ -1,56 +0,0 @@
/*
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.
*/
#ifndef __R_SHADOW_H__
#define __R_SHADOW_H__
typedef struct shadowGroup_s
{
uint bit;
texture_t *depthTexture;
vec3_t origin;
byte *vis;
float projDist;
vec3_t mins, maxs;
matrix4x4 worldviewProjectionMatrix;
struct shadowGroup_s *hashNext;
} shadowGroup_t;
extern int r_numShadowGroups;
extern shadowGroup_t r_shadowGroups[MAX_SHADOWGROUPS];
extern int r_entShadowBits[MAX_ENTITIES];
void R_InitShadows( void );
void R_ShutdownShadows( void );
qboolean R_CullPlanarShadow( struct ref_entity_s *e, vec3_t mins, vec3_t maxs, qboolean occclusionQuery );
void R_DeformVPlanarShadow( int numV, float *v );
void R_PlanarShadowPass( int state );
ref_shader_t *R_PlanarShadowShader( void );
void R_ClearShadowmaps( void );
void R_GroupShadowCasters( void );
qboolean R_AddShadowCaster( struct ref_entity_s *ent );
void R_CullShadowmapGroups( void );
void R_DrawShadowmaps( void );
#endif /*__R_SHADOW_H__*/

View File

@ -1,652 +0,0 @@
/*
Copyright (C) 1999 Stephen C. Taylor
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.
*/
// r_sky.c
#include "r_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
#define MAX_CLIP_VERTS 64
#define SIDE_SIZE 9
#define POINTS_LEN ( SIDE_SIZE * SIDE_SIZE )
#define ELEM_LEN (( SIDE_SIZE-1 ) * ( SIDE_SIZE-1 ) * 6 )
#define SPHERE_RAD 10.0f
#define EYE_RAD 9.0f
#define SCALE_S 4.0f // arbitrary (?) texture scaling factors
#define SCALE_T 4.0f
#define BOX_SIZE 1.0f
#define BOX_STEP BOX_SIZE / ( SIDE_SIZE-1 ) * 2.0f
elem_t r_skydome_elems[6][ELEM_LEN];
meshbuffer_t r_skydome_mbuffer;
static mfog_t *r_skyfog;
static msurface_t *r_warpface;
static qboolean r_warpfacevis;
static void Gen_BoxSide( skydome_t *skydome, int side, vec3_t orig, vec3_t drow, vec3_t dcol, float skyheight );
static void MakeSkyVec( float x, float y, float z, int axis, vec3_t v );
static void Gen_Box( skydome_t *skydome, float skyheight );
/*
==============
R_CreateSkydome
==============
*/
skydome_t *R_CreateSkydome( byte *mempool, float skyheight, ref_shader_t **farboxShaders, ref_shader_t **nearboxShaders )
{
int i, size;
mesh_t *mesh;
skydome_t *skydome;
byte *buffer;
size = sizeof( skydome_t ) + sizeof( mesh_t ) * 6 + sizeof( vec4_t ) * POINTS_LEN * 6 +
sizeof( vec4_t ) * POINTS_LEN * 6 + sizeof( vec2_t ) * POINTS_LEN * 12;
buffer = Mem_Alloc( mempool, size );
skydome = ( skydome_t * )buffer;
Mem_Copy( skydome->farboxShaders, farboxShaders, sizeof( ref_shader_t* ) * 6 );
Mem_Copy( skydome->nearboxShaders, nearboxShaders, sizeof( ref_shader_t* ) * 6 );
buffer += sizeof( skydome_t );
skydome->skyHeight = skyheight;
skydome->meshes = ( mesh_t* )buffer;
buffer += sizeof( mesh_t ) * 6;
for( i = 0, mesh = skydome->meshes; i < 6; i++, mesh++ )
{
mesh->numVerts = POINTS_LEN;
mesh->vertexArray = ( vec4_t * )buffer; buffer += sizeof( vec4_t ) * POINTS_LEN;
mesh->normalsArray = ( vec4_t * )buffer; buffer += sizeof( vec4_t ) * POINTS_LEN;
skydome->sphereStCoords[i] = ( vec2_t * )buffer; buffer += sizeof( vec2_t ) * POINTS_LEN;
skydome->linearStCoords[i] = ( vec2_t * )buffer; buffer += sizeof( vec2_t ) * POINTS_LEN;
mesh->numElems = ELEM_LEN;
mesh->elems = r_skydome_elems[i];
}
Gen_Box( skydome, skyheight );
return skydome;
}
/*
==============
R_FreeSkydome
==============
*/
void R_FreeSkydome( skydome_t *skydome )
{
if( skydome ) Mem_Free( skydome );
}
/*
==============
Gen_Box
==============
*/
static void Gen_Box( skydome_t *skydome, float skyheight )
{
int axis;
vec3_t orig, drow, dcol;
for( axis = 0; axis < 6; axis++ )
{
MakeSkyVec( -BOX_SIZE, -BOX_SIZE, BOX_SIZE, axis, orig );
MakeSkyVec( 0, BOX_STEP, 0, axis, drow );
MakeSkyVec( BOX_STEP, 0, 0, axis, dcol );
Gen_BoxSide( skydome, axis, orig, drow, dcol, skyheight );
}
}
/*
================
Gen_BoxSide
I don't know exactly what Q3A does for skybox texturing, but
this is at least fairly close. We tile the texture onto the
inside of a large sphere, and put the camera near the top of
the sphere. We place the box around the camera, and cast rays
through the box verts to the sphere to find the texture coordinates.
================
*/
static void Gen_BoxSide( skydome_t *skydome, int side, vec3_t orig, vec3_t drow, vec3_t dcol, float skyheight )
{
vec3_t pos, w, row, norm;
float *v, *n, *st, *st2;
float t, d, d2, b, b2, q[2], s;
int r, c;
s = 1.0 / ( SIDE_SIZE-1 );
d = EYE_RAD; // sphere center to camera distance
d2 = d * d;
b = SPHERE_RAD; // sphere radius
b2 = b * b;
q[0] = 1.0 / ( 2.0 * SCALE_S );
q[1] = 1.0 / ( 2.0 * SCALE_T );
v = skydome->meshes[side].vertexArray[0];
n = skydome->meshes[side].normalsArray[0];
st = skydome->sphereStCoords[side][0];
st2 = skydome->linearStCoords[side][0];
VectorCopy( orig, row );
VectorClear( norm );
for( r = 0; r < SIDE_SIZE; r++ )
{
VectorCopy( row, pos );
for( c = 0; c < SIDE_SIZE; c++ )
{
// pos points from eye to vertex on box
VectorScale( pos, skyheight, v );
VectorCopy( pos, w );
// Normalize pos -> w
VectorNormalize( w );
// Find distance along w to sphere
t = sqrt( d2 * ( w[2] * w[2] - 1.0 ) + b2 ) - d * w[2];
w[0] *= t;
w[1] *= t;
// use x and y on sphere as s and t
// minus is here so skies scoll in correct (Q3A's) direction
st[0] = -w[0] * q[0];
st[1] = -w[1] * q[1];
// avoid bilerp seam
st[0] = ( bound( -1, st[0], 1 ) + 1.0 ) * 0.5;
st[1] = ( bound( -1, st[1], 1 ) + 1.0 ) * 0.5;
st2[0] = c * s;
st2[1] = 1.0 - r * s;
VectorAdd( pos, dcol, pos );
VectorCopy( norm, n );
v += 4;
n += 4;
st += 2;
st2 += 2;
}
VectorAdd( row, drow, row );
}
}
/*
==============
R_DrawSkySide
==============
*/
static void R_DrawSkySide( skydome_t *skydome, int side, ref_shader_t *shader, int features )
{
meshbuffer_t *mbuffer = &r_skydome_mbuffer;
if( RI.skyMins[0][side] >= RI.skyMaxs[0][side] || RI.skyMins[1][side] >= RI.skyMaxs[1][side] )
return;
mbuffer->shaderkey = shader->sortkey;
mbuffer->dlightbits = 0;
mbuffer->sortkey = MB_FOG2NUM( r_skyfog );
skydome->meshes[side].stCoordArray = skydome->linearStCoords[side];
R_PushMesh( &skydome->meshes[side], features );
R_RenderMeshBuffer( mbuffer );
}
/*
==============
R_DrawSkyBox
==============
*/
static void R_DrawSkyBox( skydome_t *skydome, ref_shader_t **shaders )
{
int i, features;
const int skytexorder[6] = { SKYBOX_RIGHT, SKYBOX_FRONT, SKYBOX_LEFT, SKYBOX_BACK, SKYBOX_TOP, SKYBOX_BOTTOM };
features = shaders[0]->features;
if( r_shownormals->integer )
features |= MF_NORMALS;
for( i = 0; i < 6; i++ )
R_DrawSkySide( skydome, i, shaders[skytexorder[i]], features );
}
/*
==============
R_DrawBlackBottom
Draw dummy skybox side to prevent the HOM effect
==============
*/
static void R_DrawBlackBottom( skydome_t *skydome )
{
int features;
features = tr.defaultShader->features;
if( r_shownormals->integer )
features |= MF_NORMALS;
R_DrawSkySide( skydome, 5, tr.defaultShader, features );
}
/*
==============
R_DrawSky
==============
*/
void R_DrawSky( ref_shader_t *shader )
{
int i;
vec3_t mins, maxs;
matrix4x4 m, oldm;
elem_t *elem;
skydome_t *skydome;
meshbuffer_t *mbuffer = &r_skydome_mbuffer;
int u, v, umin, umax, vmin, vmax;
if( !shader ) return;
skydome = shader->skyParms ? shader->skyParms : NULL;
if( !skydome ) return;
ClearBounds( mins, maxs );
for( i = 0; i < 6; i++ )
{
if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
continue;
umin = (int)(( RI.skyMins[0][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 ));
umax = (int)(( RI.skyMaxs[0][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )) + 1;
vmin = (int)(( RI.skyMins[1][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 ));
vmax = (int)(( RI.skyMaxs[1][i] + 1.0f ) * 0.5f * (float)( SIDE_SIZE-1 )) + 1;
umin = bound( 0, umin, SIDE_SIZE-1 );
umax = bound( 0, umax, SIDE_SIZE-1 );
vmin = bound( 0, vmin, SIDE_SIZE-1 );
vmax = bound( 0, vmax, SIDE_SIZE-1 );
// box elems in tristrip order
elem = skydome->meshes[i].elems;
for( v = vmin; v < vmax; v++ )
{
for( u = umin; u < umax; u++ )
{
elem[0] = v * SIDE_SIZE + u;
elem[1] = elem[4] = elem[0] + SIDE_SIZE;
elem[2] = elem[3] = elem[0] + 1;
elem[5] = elem[1] + 1;
elem += 6;
}
}
AddPointToBounds( skydome->meshes[i].vertexArray[vmin*SIDE_SIZE+umin], mins, maxs );
AddPointToBounds( skydome->meshes[i].vertexArray[vmax*SIDE_SIZE+umax], mins, maxs );
skydome->meshes[i].numElems = ( vmax-vmin )*( umax-umin ) * 6;
}
VectorAdd( mins, RI.viewOrigin, mins );
VectorAdd( maxs, RI.viewOrigin, maxs );
if( RI.rdflags & RDF_SKYPORTALINVIEW )
{
R_DrawSkyPortal( &RI.skyportal, mins, maxs );
return;
}
// center skydome on camera to give the illusion of a larger space
Matrix4x4_Copy( oldm, RI.modelviewMatrix );
Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix );
Matrix4x4_Copy( m, RI.worldviewMatrix );
if( shader->skySpeed )
{
float angle = shader->skySpeed * RI.refdef.time;
Matrix4x4_ConcatRotate( m, angle, shader->skyAxis[0], shader->skyAxis[1], shader->skyAxis[2] );
}
Matrix4x4_SetOrigin( m, 0, 0, 0 );
m[3][3] = 1.0f;
GL_LoadMatrix( m );
gldepthmin = 1;
gldepthmax = 1;
pglDepthRange( gldepthmin, gldepthmax );
if( RI.params & RP_CLIPPLANE )
pglDisable( GL_CLIP_PLANE0 );
// it can happen that sky surfaces have no fog hull specified
// yet there's a global fog hull (see wvwq3dm7)
if( !r_skyfog ) r_skyfog = r_worldbrushmodel->globalfog;
if( skydome->farboxShaders[0] )
R_DrawSkyBox( skydome, skydome->farboxShaders );
else R_DrawBlackBottom( skydome );
if( shader->num_stages )
{
qboolean flush = false;
int features = shader->features;
if( r_shownormals->integer )
features |= MF_NORMALS;
for( i = 0; i < 6; i++ )
{
if( RI.skyMins[0][i] >= RI.skyMaxs[0][i] || RI.skyMins[1][i] >= RI.skyMaxs[1][i] )
continue;
flush = true;
mbuffer->shaderkey = shader->sortkey;
mbuffer->dlightbits = 0;
mbuffer->sortkey = MB_FOG2NUM( r_skyfog );
skydome->meshes[i].stCoordArray = skydome->sphereStCoords[i];
R_PushMesh( &skydome->meshes[i], features );
}
if( flush ) R_RenderMeshBuffer( mbuffer );
}
if( skydome->nearboxShaders[0] )
R_DrawSkyBox( skydome, skydome->nearboxShaders );
if( RI.params & RP_CLIPPLANE )
pglEnable( GL_CLIP_PLANE0 );
Matrix4x4_Copy( RI.modelviewMatrix, oldm );
GL_LoadMatrix( RI.worldviewMatrix );
gldepthmin = 0;
gldepthmax = 1;
pglDepthRange( gldepthmin, gldepthmax );
r_skyfog = NULL;
}
//===================================================================
vec3_t skyclip[6] =
{
{ 1, 1, 0 },
{ 1, -1, 0 },
{ 0, -1, 1 },
{ 0, 1, 1 },
{ 1, 0, 1 },
{ -1, 0, 1 }
};
// 1 = s, 2 = t, 3 = 2048
int st_to_vec[6][3] =
{
{ 3, -1, 2 },
{ -3, 1, 2 },
{ 1, 3, 2 },
{ -1, -3, 2 },
{ -2, -1, 3 }, // 0 degrees yaw, look straight up
{ 2, -1, -3 } // look straight down
};
// s = [0]/[2], t = [1]/[2]
int vec_to_st[6][3] =
{
{ -2, 3, 1 },
{ 2, 3, -1 },
{ 1, 3, 2 },
{ -1, 3, -2 },
{ -2, -1, 3 },
{ -2, 1, -3 }
};
/*
==============
DrawSkyPolygon
==============
*/
void DrawSkyPolygon( int nump, vec3_t vecs )
{
int i, j;
vec3_t v, av;
float s, t, dv;
int axis;
float *vp;
// decide which face it maps to
VectorClear( v );
for( i = 0, vp = vecs; i < nump; i++, vp += 3 )
VectorAdd( vp, v, v );
av[0] = fabs( v[0] );
av[1] = fabs( v[1] );
av[2] = fabs( v[2] );
if(( av[0] > av[1] ) && ( av[0] > av[2] ))
axis = ( v[0] < 0 ) ? 1 : 0;
else if(( av[1] > av[2] ) && ( av[1] > av[0] ))
axis = ( v[1] < 0 ) ? 3 : 2;
else axis = ( v[2] < 0 ) ? 5 : 4;
if( !r_skyfog )
r_skyfog = r_warpface->fog;
r_warpfacevis = true;
// project new texture coords
for( i = 0; i < nump; i++, vecs += 3 )
{
j = vec_to_st[axis][2];
dv = ( j > 0 ) ? vecs[j - 1] : -vecs[-j - 1];
if( dv < 0.001f )
continue; // don't divide by zero
dv = 1.0f / dv;
j = vec_to_st[axis][0];
s = ( j < 0 ) ? -vecs[-j -1] * dv : vecs[j-1] * dv;
j = vec_to_st[axis][1];
t = ( j < 0 ) ? -vecs[-j -1] * dv : vecs[j-1] * dv;
if( s < RI.skyMins[0][axis] ) RI.skyMins[0][axis] = s;
if( t < RI.skyMins[1][axis] ) RI.skyMins[1][axis] = t;
if( s > RI.skyMaxs[0][axis] ) RI.skyMaxs[0][axis] = s;
if( t > RI.skyMaxs[1][axis] ) RI.skyMaxs[1][axis] = t;
}
}
/*
==============
ClipSkyPolygon
==============
*/
void ClipSkyPolygon( int nump, vec3_t vecs, int stage )
{
float *norm;
float *v;
qboolean front, back;
float d, e;
float dists[MAX_CLIP_VERTS + 1];
int sides[MAX_CLIP_VERTS + 1];
vec3_t newv[2][MAX_CLIP_VERTS + 1];
int newc[2];
int i, j;
if( nump > MAX_CLIP_VERTS )
Host_Error( "ClipSkyPolygon: MAX_CLIP_VERTS\n" );
loc1:
if( stage == 6 )
{
// fully clipped, so draw it
DrawSkyPolygon( nump, vecs );
return;
}
front = back = false;
norm = skyclip[stage];
for( i = 0, v = vecs; i < nump; i++, v += 3 )
{
d = DotProduct( v, norm );
if( d > ON_EPSILON )
{
front = true;
sides[i] = SIDE_FRONT;
}
else if( d < -ON_EPSILON )
{
back = true;
sides[i] = SIDE_BACK;
}
else
{
sides[i] = SIDE_ON;
}
dists[i] = d;
}
if( !front || !back )
{
// not clipped
stage++;
goto loc1;
}
// clip it
sides[i] = sides[0];
dists[i] = dists[0];
VectorCopy( vecs, ( vecs + ( i * 3 )));
newc[0] = newc[1] = 0;
for( i = 0, v = vecs; i < nump; i++, v += 3 )
{
switch( sides[i] )
{
case SIDE_FRONT:
VectorCopy( v, newv[0][newc[0]] );
newc[0]++;
break;
case SIDE_BACK:
VectorCopy( v, newv[1][newc[1]] );
newc[1]++;
break;
case SIDE_ON:
VectorCopy( v, newv[0][newc[0]] );
newc[0]++;
VectorCopy( v, newv[1][newc[1]] );
newc[1]++;
break;
}
if( sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i] )
continue;
d = dists[i] / ( dists[i] - dists[i+1] );
for( j = 0; j < 3; j++ )
{
e = v[j] + d * ( v[j+3] - v[j] );
newv[0][newc[0]][j] = e;
newv[1][newc[1]][j] = e;
}
newc[0]++;
newc[1]++;
}
// continue
ClipSkyPolygon( newc[0], newv[0][0], stage + 1 );
ClipSkyPolygon( newc[1], newv[1][0], stage + 1 );
}
/*
=================
R_AddSkySurface
=================
*/
qboolean R_AddSkySurface( msurface_t *fa )
{
int i;
vec4_t *vert;
elem_t *elem;
mesh_t *mesh;
vec3_t verts[4];
// calculate vertex values for sky box
r_warpface = fa;
r_warpfacevis = false;
if( tr.currentSkyShader && tr.currentSkyShader->skySpeed )
{
// HACK: force full sky to draw when rotating
for( i = 0; i < 6; i++ )
{
RI.skyMins[0][i] = RI.skyMins[1][i] = -1;
RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = 1;
}
}
mesh = fa->mesh;
elem = mesh->elems;
vert = mesh->vertexArray;
for( i = 0; i < mesh->numElems; i += 3, elem += 3 )
{
VectorSubtract( vert[elem[0]], RI.viewOrigin, verts[0] );
VectorSubtract( vert[elem[1]], RI.viewOrigin, verts[1] );
VectorSubtract( vert[elem[2]], RI.viewOrigin, verts[2] );
ClipSkyPolygon( 3, verts[0], 0 );
}
return r_warpfacevis;
}
/*
==============
R_ClearSkyBox
==============
*/
void R_ClearSkyBox( void )
{
int i;
RI.params |= RP_NOSKY;
for( i = 0; i < 6; i++ )
{
RI.skyMins[0][i] = RI.skyMins[1][i] = 9999999;
RI.skyMaxs[0][i] = RI.skyMaxs[1][i] = -9999999;
}
}
static void MakeSkyVec( float x, float y, float z, int axis, vec3_t v )
{
int j, k;
vec3_t b;
VectorSet( b, x, y, z );
for( j = 0; j < 3; j++ )
{
k = st_to_vec[axis][j];
if( k < 0 ) v[j] = -b[-k-1];
else v[j] = b[k-1];
}
}

View File

@ -1,891 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// r_sprite.c - render sprite models
//=======================================================================
#include "r_local.h"
#include "mathlib.h"
#include "const.h"
#include "cl_entity.h"
/*
=============================================================
SPRITE MODELS
=============================================================
*/
string frame_prefix;
uint frame_type;
uint group_num;
string sp_name;
ref_shader_t **frames = NULL;
convar_t *r_sprite_lerping;
uint tex_flags = 0;
vec3_t sprite_mins, sprite_maxs;
float sprite_radius;
/*
====================
R_SpriteInit
====================
*/
void R_SpriteInit( void )
{
r_sprite_lerping = Cvar_Get( "r_sprite_lerping", "1", CVAR_ARCHIVE, "enables sprite model animation lerping" );
}
/*
====================
Sprite model loader
====================
*/
static dframetype_t *R_SpriteLoadFrame( ref_model_t *mod, void *pin, mspriteframe_t **ppframe, int framenum )
{
texture_t *tex;
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
string name, shadername;
// build uinque frame name
if( !sp_name[0] ) FS_FileBase( mod->name, sp_name );
com.snprintf( name, MAX_STRING, "Sprite( %s_%s_%i%i )", sp_name, frame_prefix, framenum/10, framenum%10 );
pinframe = (dspriteframe_t *)pin;
// setup frame description
pspriteframe = Mem_Alloc( mod->mempool, sizeof( mspriteframe_t ));
pspriteframe->width = pinframe->width;
pspriteframe->height = pinframe->height;
pspriteframe->up = pinframe->origin[1];
pspriteframe->left = pinframe->origin[0];
pspriteframe->down = pinframe->origin[1] - pinframe->height;
pspriteframe->right = pinframe->width + pinframe->origin[0];
pspriteframe->radius = com.sqrt((pinframe->width * pinframe->width) + (pinframe->height * pinframe->height));
tex = R_FindTexture( name, (byte *)pin, pinframe->width * pinframe->height, 0 );
tex_flags |= tex->flags;
*ppframe = pspriteframe;
R_ShaderAddStageTexture( tex );
if( frame_type == FRAME_SINGLE )
{
com.snprintf( shadername, MAX_STRING, "sprites/%s.spr/%s_%i%i )", sp_name, frame_prefix, framenum/10, framenum%10 );
pspriteframe->shader = R_LoadShader( shadername, SHADER_SPRITE, true, tex_flags, SHADER_INVALID )->shadernum;
frames = Mem_Realloc( mod->mempool, frames, sizeof( ref_shader_t* ) * (mod->numshaders + 1));
frames[mod->numshaders++] = &r_shaders[pspriteframe->shader];
}
return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height );
}
static dframetype_t *CL_LoadSpriteFrame( const char *szSpriteName, void *pin, int framenum )
{
texture_t *tex;
string name;
dspriteframe_t *pinframe;
// build uinque frame name
if( !sp_name[0] ) FS_FileBase( szSpriteName, sp_name );
com.snprintf( name, MAX_STRING, "Sprite( \"%s_%s_%i%i\" )", sp_name, frame_prefix, framenum/10, framenum%10 );
pinframe = (dspriteframe_t *)pin;
// NOTE: just loading all single frame into one shader
// we supported only single frames in this case
// because we can't properly merge multiple groups into single shader
tex = R_FindTexture( name, (byte *)pin, pinframe->width * pinframe->height, tex_flags );
R_ShaderAddStageTexture( tex );
return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height );
}
static dframetype_t *CL_SpriteSkipGroup( const char *szSpriteName, void *pin, int framenum )
{
dspritegroup_t *pingroup;
dspriteinterval_t *pin_intervals;
dspriteframe_t *pinframe;
void *ptemp;
int i;
// throw warning
MsgDev( D_WARN, "CL_LoadSprite: %s ignore group frame %i\n", szSpriteName, framenum );
pingroup = (dspritegroup_t *)pin;
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
// skip intervals
for( i = 0; i < pingroup->numframes; i++ )
pin_intervals++;
// skip group frames
ptemp = (void *)pin_intervals;
for( i = 0; i < pingroup->numframes; i++ )
{
pinframe = (dspriteframe_t *)ptemp;
ptemp = (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height );
}
return (dframetype_t *)ptemp;
}
static dframetype_t *R_SpriteLoadGroup( ref_model_t *mod, void * pin, mspriteframe_t **ppframe, int framenum )
{
dspritegroup_t *pingroup;
mspritegroup_t *pspritegroup;
dspriteinterval_t *pin_intervals;
float *poutintervals;
shader_t group_shader;
int i, groupsize, numframes;
string shadername;
void *ptemp;
pingroup = (dspritegroup_t *)pin;
numframes = pingroup->numframes;
groupsize = sizeof(mspritegroup_t) + (numframes - 1) * sizeof( pspritegroup->frames[0] );
pspritegroup = Mem_Alloc( mod->mempool, groupsize );
pspritegroup->numframes = numframes;
*ppframe = (mspriteframe_t *)pspritegroup;
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
poutintervals = Mem_Alloc( mod->mempool, numframes * sizeof( float ));
pspritegroup->intervals = poutintervals;
for( i = 0; i < numframes; i++ )
{
*poutintervals = pin_intervals->interval;
if( *poutintervals <= 0.0 ) *poutintervals = 1.0f; // set error value
if( frame_type == FRAME_GROUP ) R_ShaderAddStageIntervals( *poutintervals );
else if( frame_type == FRAME_ANGLED ) R_ShaderAddStageIntervals( -1.0f );
poutintervals++;
pin_intervals++;
}
ptemp = (void *)pin_intervals;
for( i = 0; i < numframes; i++ )
{
ptemp = R_SpriteLoadFrame( mod, ptemp, &pspritegroup->frames[i], framenum * 10 + i );
}
com.snprintf( shadername, MAX_STRING, "sprites/%s.spr/%s_%i%i", sp_name, frame_prefix, group_num/10, group_num%10 );
group_shader = R_LoadShader( shadername, SHADER_SPRITE, true, tex_flags, SHADER_INVALID )->shadernum;
frames = Mem_Realloc( mod->mempool, frames, sizeof( ref_shader_t* ) * (mod->numshaders + 1));
frames[mod->numshaders++] = &r_shaders[group_shader];
// apply this shader for all frames in group
for( i = 0; i < numframes; i++ )
pspritegroup->frames[i]->shader = group_shader;
group_num++;
return (dframetype_t *)ptemp;
}
void Mod_SpriteLoadModel( ref_model_t *mod, const void *buffer )
{
dsprite_t *pin;
short *numi;
msprite_t *psprite;
dframetype_t *pframetype;
int i, size, numframes;
qboolean twoSided;
pin = (dsprite_t *)buffer;
i = pin->version;
if( i != SPRITE_VERSION )
{
MsgDev( D_ERROR, "%s has wrong version number (%i should be %i)\n", mod->name, i, SPRITE_VERSION );
return;
}
numframes = pin->numframes;
size = sizeof( msprite_t ) + ( numframes - 1 ) * sizeof( psprite->frames );
psprite = Mem_Alloc( mod->mempool, size );
mod->extradata = psprite; // make link to extradata
mod->numshaders = 0; // reset frames
psprite->type = pin->type;
psprite->rendermode = pin->texFormat;
psprite->numframes = numframes;
twoSided = ( pin->facetype == SPR_CULL_NONE ) ? true : false;
mod->mins[0] = mod->mins[1] = -pin->bounds[0] / 2;
mod->maxs[0] = mod->maxs[1] = pin->bounds[0] / 2;
mod->mins[2] = -pin->bounds[1] / 2;
mod->maxs[2] = pin->bounds[1] / 2;
numi = (short *)(pin + 1);
if( *numi == 256 )
{
byte *src = (byte *)(numi+1);
rgbdata_t *pal;
// install palette
switch( psprite->rendermode )
{
case SPR_ADDGLOW:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderGlow, twoSided );
break;
case SPR_ADDITIVE:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderTransAdd, twoSided );
break;
case SPR_INDEXALPHA:
pal = FS_LoadImage( "#decal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderTransTexture, twoSided );
break;
case SPR_ALPHTEST:
pal = FS_LoadImage( "#transparent.pal", src, 768 );
R_ShaderSetRenderMode( kRenderTransAlpha, twoSided );
break;
case SPR_NORMAL:
default:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
}
pframetype = (dframetype_t *)(src + 768);
FS_FreeImage( pal ); // palette installed, no reason to keep this data
}
else
{
MsgDev( D_ERROR, "%s has wrong number of palette colors %i (should be 256)\n", mod->name, numi );
return;
}
if( numframes < 1 )
{
MsgDev( D_ERROR, "%s has invalid # of frames: %d\n", mod->name, numframes );
return;
}
mod->touchFrame = tr.registration_sequence;
frames = NULL; // invalidate pointer
sp_name[0] = 0;
group_num = 0;
for( i = 0; i < numframes; i++ )
{
frametype_t frametype = pframetype->type;
psprite->frames[i].type = frametype;
frame_type = frametype;
switch( frametype )
{
case FRAME_SINGLE:
tex_flags = 0;
com.strncpy( frame_prefix, "one", MAX_STRING );
pframetype = R_SpriteLoadFrame( mod, pframetype + 1, &psprite->frames[i].frameptr, i );
break;
case FRAME_GROUP:
tex_flags = 0;
com.strncpy( frame_prefix, "grp", MAX_STRING );
pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i );
break;
case FRAME_ANGLED:
tex_flags = 0;
com.strncpy( frame_prefix, "ang", MAX_STRING );
pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i );
break;
}
if( pframetype == NULL ) break; // technically an error
}
mod->shaders = frames; // setup texture links
mod->type = mod_sprite;
}
/*
================
CL_LoadSprite
client version for loading sprites
and convert them to shaders with multiple frames
================
*/
ref_shader_t *CL_LoadSprite( const char *szSpriteName )
{
dsprite_t *pin;
ref_shader_t *shader;
byte *buffer;
dframetype_t *pframetype;
qboolean twoSided;
int i, numframes;
short *numi;
if( !szSpriteName || !szSpriteName[0] )
return r_shaders;
shader = R_FindShader( szSpriteName, SHADER_SPRITE, SHADER_INVALID );
if( shader ) return shader; // already loaded
buffer = FS_LoadFile( szSpriteName, NULL );
if( !buffer ) return r_shaders; // sprite is missed
pin = (dsprite_t *)buffer;
// make sure what is really sprite
if( pin->ident != IDSPRITEHEADER )
{
MsgDev( D_ERROR, "CL_LoadSprite: %s not a sprite\n", szSpriteName );
Mem_Free( buffer );
return r_shaders;
}
if( pin->version != SPRITE_VERSION )
{
MsgDev( D_ERROR, "CL_LoadSprite: %s invalid sprite version\n", szSpriteName );
Mem_Free( buffer );
return r_shaders;
}
numframes = pin->numframes;
twoSided = ( pin->facetype == SPR_CULL_NONE ) ? true : false;
numi = (short *)( pin + 1 );
// NOTE: TriAPI and hud sprites not used auto-rendermode feature
if( *numi == 256 )
{
byte *src = (byte *)(numi+1);
rgbdata_t *pal;
// install palette
switch( pin->texFormat )
{
case SPR_ADDGLOW:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
case SPR_ADDITIVE:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
case SPR_INDEXALPHA:
pal = FS_LoadImage( "#decal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
case SPR_ALPHTEST:
pal = FS_LoadImage( "#transparent.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
case SPR_NORMAL:
default:
pal = FS_LoadImage( "#normal.pal", src, 768 );
R_ShaderSetRenderMode( kRenderNormal, twoSided );
break;
}
pframetype = (dframetype_t *)(src + 768);
FS_FreeImage( pal ); // palette installed, no reason to keep this data
}
else
{
MsgDev( D_ERROR, "CL_LoadSprite: %s has invalid palette\n", szSpriteName );
Mem_Free( buffer );
return r_shaders;
}
if( numframes < 1 )
{
MsgDev( D_ERROR, "CL_LoadSprite: %s has invalid # of frames: %d\n", szSpriteName, numframes );
Mem_Free( buffer );
return r_shaders;
}
com.strncpy( frame_prefix, "one", MAX_STRING );
tex_flags = TF_CLAMP|TF_NOMIPMAP|TF_NOPICMIP;
frames = NULL; // invalidate pointer
sp_name[0] = 0;
group_num = 0;
for( i = 0; i < numframes; i++ )
{
switch( pframetype->type )
{
case FRAME_SINGLE:
pframetype = CL_LoadSpriteFrame( szSpriteName, pframetype + 1, i );
break;
case FRAME_GROUP:
case FRAME_ANGLED:
pframetype = CL_SpriteSkipGroup( szSpriteName, pframetype + 1, i );
break;
}
if( pframetype == NULL ) break; // technically an error
}
// all frames uploaded, release buffer
Mem_Free( buffer );
return R_LoadShader( szSpriteName, SHADER_SPRITE, true, tex_flags, SHADER_INVALID );
}
/*
================
R_GetSpriteFrame
assume pModel is valid
================
*/
mspriteframe_t *R_GetSpriteFrame( ref_model_t *pModel, int frame, float yawAngle )
{
msprite_t *psprite;
int i, numframes;
mspritegroup_t *pspritegroup;
mspriteframe_t *pspriteframe;
float *pintervals, fullinterval, targettime, time;
ASSERT( pModel );
psprite = pModel->extradata;
if( frame < 0 )
{
frame = 0;
}
else if( frame >= psprite->numframes )
{
MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name );
frame = psprite->numframes - 1;
}
if( psprite->frames[frame].type == FRAME_SINGLE )
{
pspriteframe = psprite->frames[frame].frameptr;
}
else if( psprite->frames[frame].type == FRAME_GROUP )
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pintervals = pspritegroup->intervals;
numframes = pspritegroup->numframes;
fullinterval = pintervals[numframes-1];
time = RI.refdef.time;
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by zero
targettime = time - ((int)(time / fullinterval)) * fullinterval;
for( i = 0; i < (numframes - 1); i++ )
{
if( pintervals[i] > targettime )
break;
}
pspriteframe = pspritegroup->frames[i];
}
else if( psprite->frames[frame].type == FRAME_ANGLED )
{
// e.g. doom-style sprite monsters
float yaw = yawAngle - 45; // angled bias
int angleframe = (int)(( RI.refdef.viewangles[1] - yaw ) / 360 * 8 + 0.5 - 4) & 7;
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pspriteframe = pspritegroup->frames[angleframe];
}
return pspriteframe;
}
/*
================
R_GetSpriteFrameInterpolant
NOTE: we using prevblending[0] and [1] for holds interval
between frames where are we lerping
================
*/
float R_GetSpriteFrameInterpolant( ref_entity_t *ent, mspriteframe_t **oldframe, mspriteframe_t **curframe )
{
msprite_t *psprite;
mspritegroup_t *pspritegroup;
int i, j, numframes, frame;
float lerpFrac, time, jtime, jinterval;
float *pintervals, fullinterval, targettime;
int m_fDoInterp;
psprite = ent->model->extradata;
frame = (int)ent->lerp->curstate.frame;
lerpFrac = 1.0f;
// misc info
if( r_sprite_lerping->integer )
m_fDoInterp = (ent->flags & EF_NOINTERP) ? false : true;
else m_fDoInterp = false;
if( frame < 0 )
{
frame = 0;
}
else if( frame >= psprite->numframes )
{
MsgDev( D_WARN, "R_GetSpriteFrame: no such frame %d (%s)\n", frame, ent->model->name );
frame = psprite->numframes - 1;
}
if( psprite->frames[frame].type == FRAME_SINGLE )
{
if( m_fDoInterp )
{
if( ent->lerp->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->lerp->latched.prevblending[0]].type != FRAME_SINGLE )
{
// this can be happens when rendering switched between single and angled frames
// or change model on replace delta-entity
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 1.0f;
}
if( ent->lerp->latched.prevanimtime < RI.refdef.time )
{
if( frame != ent->lerp->latched.prevblending[1] )
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1];
ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 0.0f;
}
else lerpFrac = (RI.refdef.time - ent->lerp->latched.prevanimtime) * ent->framerate;
}
else
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 0.0f;
}
}
else
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
lerpFrac = 1.0f;
}
if( ent->lerp->latched.prevblending[0] >= psprite->numframes )
{
// reset interpolation on change model
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 0.0f;
}
// get the interpolated frames
if( oldframe ) *oldframe = psprite->frames[ent->lerp->latched.prevblending[0]].frameptr;
if( curframe ) *curframe = psprite->frames[frame].frameptr;
}
else if( psprite->frames[frame].type == FRAME_GROUP )
{
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
pintervals = pspritegroup->intervals;
numframes = pspritegroup->numframes;
fullinterval = pintervals[numframes-1];
jinterval = pintervals[1] - pintervals[0];
time = RI.refdef.time;
jtime = 0.0f;
// when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
// are positive, so we don't have to worry about division by zero
targettime = time - ((int)(time / fullinterval)) * fullinterval;
// LordHavoc: since I can't measure the time properly when it loops from numframes - 1 to 0,
// i instead measure the time of the first frame, hoping it is consistent
for( i = 0, j = numframes - 1; i < (numframes - 1); i++ )
{
if( pintervals[i] > targettime )
break;
j = i;
jinterval = pintervals[i] - jtime;
jtime = pintervals[i];
}
if( m_fDoInterp )
lerpFrac = (targettime - jtime) / jinterval;
else j = i; // no lerping
// get the interpolated frames
if( oldframe ) *oldframe = pspritegroup->frames[j];
if( curframe ) *curframe = pspritegroup->frames[i];
}
else if( psprite->frames[frame].type == FRAME_ANGLED )
{
// e.g. doom-style sprite monsters
float yaw = ent->angles[1] - 45; // angled bias
int angleframe = (int)((RI.refdef.viewangles[1] - yaw) / 360 * 8 + 0.5 - 4) & 7;
if( m_fDoInterp )
{
if( ent->lerp->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->lerp->latched.prevblending[0]].type != FRAME_ANGLED )
{
// this can be happens when rendering switched between single and angled frames
// or change model on replace delta-entity
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 1.0f;
}
if( ent->lerp->latched.prevanimtime < RI.refdef.time )
{
if( frame != ent->lerp->latched.prevblending[1] )
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1];
ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 0.0f;
}
else lerpFrac = (RI.refdef.time - ent->lerp->latched.prevanimtime) * ent->framerate;
}
else
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
ent->lerp->latched.prevanimtime = RI.refdef.time;
lerpFrac = 0.0f;
}
}
else
{
ent->lerp->latched.prevblending[0] = ent->lerp->latched.prevblending[1] = frame;
lerpFrac = 1.0f;
}
pspritegroup = (mspritegroup_t *)psprite->frames[ent->lerp->latched.prevblending[0]].frameptr;
if( oldframe ) *oldframe = pspritegroup->frames[angleframe];
pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
if( curframe ) *curframe = pspritegroup->frames[angleframe];
}
return lerpFrac;
}
static float R_GlowSightDistance( vec3_t glowOrigin )
{
float dist;
vec3_t glowDist;
pmtrace_t tr;
VectorSubtract( glowOrigin, RI.viewOrigin, glowDist );
dist = VectorLength( glowDist );
R_TraceLine( &tr, RI.viewOrigin, glowOrigin, FTRACE_IGNORE_GLASS|FTRACE_SIMPLEBOX );
if(( 1.0f - tr.fraction ) * dist > 8 )
return -1;
return dist;
}
static float R_SpriteGlowBlend( ref_entity_t *e )
{
float dist = R_GlowSightDistance( e->origin );
float brightness;
if( dist <= 0 ) return 0.0f; // occluded
if( e->renderfx == kRenderFxNoDissipation )
return (float)e->renderamt * (1.0f/255.0f);
// UNDONE: Tweak these magic numbers (19000 - falloff & 200 - sprite size)
brightness = 19000.0 / ( dist * dist );
brightness = bound( 0.05f, brightness, 1.0f );
// Make the glow fixed size in screen space, taking into consideration the scale setting.
if( e->scale == 0 ) e->scale = 1.0f;
e->scale *= dist * (1.0f / 200.0f );
return brightness;
}
qboolean R_SpriteOccluded( ref_entity_t *e )
{
if( e->rendermode == kRenderGlow )
{
float blend = 1.0f;
float depth;
vec3_t v;
R_TransformToScreen_Vec3( e->origin, v );
if( v[0] < RI.refdef.viewport[0] || v[0] > RI.refdef.viewport[0] + RI.refdef.viewport[2] )
return true; // do scissor
if( v[1] < RI.refdef.viewport[1] || v[1] > RI.refdef.viewport[1] + RI.refdef.viewport[3] )
return true; // do scissor
if( r_cullflares->integer )
{
pglReadPixels((int)( v[0] ), (int)( v[1] ), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth );
if( depth + 1e-4 < v[2] ) return true; // occluded
}
blend *= R_SpriteGlowBlend( e );
e->renderamt *= blend;
if( blend <= 0.05f )
return true; // faded
}
return false;
}
/*
=================
R_DrawSpriteModel
=================
*/
void R_DrawSpriteModel( const meshbuffer_t *mb )
{
ref_entity_t *e;
mspriteframe_t *frame, *oldframe;
msprite_t *psprite;
ref_model_t *model;
float lerp = 1.0f, ilerp;
meshbuffer_t *rb = (meshbuffer_t *)mb;
byte renderamt;
MB_NUM2ENTITY( mb->sortkey, e );
model = e->model;
if( OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ))
{
ref_shader_t *shader;
MB_NUM2SHADER( mb->shaderkey, shader );
if( !R_GetOcclusionQueryResultBool( shader->type == 1 ? OQ_PLANARSHADOW : OQ_ENTITY, e - r_entities, true ))
return;
}
psprite = (msprite_t * )model->extradata;
switch( e->rendermode )
{
case kRenderNormal:
case kRenderTransColor:
case kRenderTransAlpha:
frame = oldframe = R_GetSpriteFrame( e->model, e->lerp->curstate.frame, e->angles[YAW] );
break;
case kRenderTransTexture:
case kRenderTransAdd:
case kRenderGlow:
lerp = R_GetSpriteFrameInterpolant( e, &oldframe, &frame );
break;
default:
Host_Error( "R_DrawSpriteModel: %s bad rendermode %i\n", model->name, e->rendermode );
break;
}
// do movewith
if( e->parent && e->movetype == MOVETYPE_FOLLOW )
{
if( e->body > 0 && e->parent->model && e->parent->model->type == mod_studio )
{
int num = bound( 1, e->body, MAXSTUDIOATTACHMENTS );
// pev->colormap is hardcoded to attachment number
// NOTE: use interpolated origin to avoid flickering attachments
VectorCopy( e->parent->lerp->attachment[num-1], e->origin2 );
}
else VectorCopy( e->parent->origin, e->origin2 );
}
// no rotation for sprites
R_TranslateForEntity( e );
if( e->rendermode == kRenderGlow )
pglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ));
if( oldframe == frame )
{
// draw the single non-lerped frame
if( R_PushSprite( rb, psprite->type, frame->left, frame->right, frame->down, frame->up ))
R_RenderMeshBuffer( rb );
}
else
{
// draw two combined lerped frames
renderamt = e->renderamt;
lerp = bound( 0.0f, lerp, 1.0f );
ilerp = 1.0f - lerp;
if( ilerp != 0 )
{
e->renderamt = renderamt * ilerp; // merge prevframe alpha
if( e->customShader ) rb->shaderkey = e->customShader->sortkey;
else rb->shaderkey = r_shaders[oldframe->shader].sortkey;
if( R_PushSprite( rb, psprite->type, oldframe->left, oldframe->right, oldframe->down, oldframe->up ))
R_RenderMeshBuffer( rb );
}
if( lerp != 0 )
{
e->renderamt = renderamt * lerp; // merge frame alpha
if( e->customShader ) rb->shaderkey = e->customShader->sortkey;
else rb->shaderkey = r_shaders[frame->shader].sortkey;
if( R_PushSprite( rb, psprite->type, frame->left, frame->right, frame->down, frame->up ))
R_RenderMeshBuffer( rb );
}
// restore current values (e.g. for right mirror passes)
e->renderamt = renderamt;
}
if( e->rendermode == kRenderGlow )
pglDepthRange( gldepthmin, gldepthmax );
}
qboolean R_CullSpriteModel( ref_entity_t *e )
{
qboolean frustum, query, clipped;
if( !e->model->extradata )
return true;
if( e->ent_type == ET_VIEWENTITY && r_lefthand->integer >= 2 )
return true;
VectorCopy( e->model->mins, sprite_mins );
VectorCopy( e->model->maxs, sprite_maxs );
sprite_radius = RadiusFromBounds( sprite_mins, sprite_maxs );
clipped = R_CullModel( e, sprite_mins, sprite_maxs, sprite_radius );
frustum = clipped & 1;
if( clipped & 2 ) return true;
query = OCCLUSION_QUERIES_ENABLED( RI ) && OCCLUSION_TEST_ENTITY( e ) ? true : false;
if( !frustum && query ) R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_ENTITY, e - r_entities ), e, sprite_mins, sprite_maxs );
return frustum;
}
void R_SpriteDrawDebug( void )
{
vec3_t bbox[8];
ref_model_t *model;
int i;
if( r_drawentities->integer != 5 )
return;
model = RI.currententity->model;
// compute a full bounding box
for( i = 0; i < 8; i++ )
{
bbox[i][0] = (i & 1) ? model->mins[0] : model->maxs[0];
bbox[i][1] = (i & 2) ? model->mins[1] : model->maxs[1];
bbox[i][2] = (i & 4) ? model->mins[2] : model->maxs[2];
}
R_TranslateForEntity( RI.currententity );
pglColor4f( 0.0f, 0.0f, 1.0f, 1.0f ); // blue bboxes for sprites
pglBegin( GL_LINES );
for( i = 0; i < 2; i += 1 )
{
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i*2+0] );
pglVertex3fv( bbox[i*2+1] );
pglVertex3fv( bbox[i*2+4] );
pglVertex3fv( bbox[i*2+5] );
}
pglEnd();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,718 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
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.
*/
// r_surf.c: surface-related refresh code
#include "r_local.h"
#include "mathlib.h"
#include "matrix_lib.h"
#include "bspfile.h"
static vec3_t modelorg; // relative to viewpoint
static vec3_t modelmins;
static vec3_t modelmaxs;
static byte fatpvs[MAX_MAP_LEAFS/8];
/*
=============================================================
BRUSH MODELS
=============================================================
*/
/*
=================
R_SurfPotentiallyVisible
=================
*/
qboolean R_SurfPotentiallyVisible( msurface_t *surf )
{
if( !surf->texinfo )
return false;
if( !surf->mesh || R_InvalidMesh( surf->mesh ))
return false;
if( !surf->shader )
return false;
if( !surf->shader->num_stages )
return false;
return true;
}
/*
=================
R_CullSurface
=================
*/
qboolean R_CullSurface( msurface_t *surf, uint clipflags )
{
ref_shader_t *shader = surf->shader;
if(( shader->flags & SHADER_SKYPARMS ) && r_fastsky->integer )
return true;
if( surf->flags & SURF_WATERCSG && !( RI.currententity->flags & EF_NOWATERCSG ))
return true;
if( r_nocull->integer )
return false;
if( shader->tessSize )
return false;
if( shader->flags & SHADER_AUTOSPRITE )
return false;
if( r_faceplanecull->integer && ( shader->flags & (SHADER_CULL_FRONT|SHADER_CULL_BACK)))
{
if( !VectorCompare( surf->plane->normal, vec3_origin ))
{
float dist;
dist = PlaneDiff( modelorg, surf->plane );
if( shader->flags & SHADER_CULL_FRONT || ( RI.params & RP_MIRRORVIEW ))
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
}
else if( shader->flags & SHADER_CULL_BACK )
{
if( surf->flags & SURF_PLANEBACK )
{
if( dist <= BACKFACE_EPSILON )
return true; // wrong side
}
else
{
if( dist >= -BACKFACE_EPSILON )
return true; // wrong side
}
}
}
}
return ( clipflags && R_CullBox( surf->mins, surf->maxs, clipflags ));
}
/*
=================
R_AddSurfaceToList
=================
*/
static meshbuffer_t *R_AddSurfaceToList( msurface_t *surf, unsigned int clipflags )
{
ref_shader_t *shader;
meshbuffer_t *mb;
if( R_CullSurface( surf, clipflags ))
return NULL;
shader = ((r_drawworld->integer == 2) ? R_OcclusionShader() : surf->shader);
if( shader->flags & SHADER_SKYPARMS )
{
qboolean vis = R_AddSkySurface( surf );
if(( RI.params & RP_NOSKY ) && vis )
{
R_AddMeshToList( MB_MODEL, surf->fog, shader, surf - r_worldbrushmodel->surfaces + 1 );
RI.params &= ~RP_NOSKY;
}
return NULL;
}
if( OCCLUSION_QUERIES_ENABLED( RI ))
{
if( shader->flags & SHADER_PORTAL )
R_SurfOcclusionQueryKey( RI.currententity, surf );
if( OCCLUSION_OPAQUE_SHADER( shader ) )
R_AddOccludingSurface( surf, shader );
}
c_brush_polys++;
mb = R_AddMeshToList( MB_MODEL, surf->fog, shader, surf - r_worldbrushmodel->surfaces + 1 );
RI.surfmbuffers[surf - r_worldbrushmodel->surfaces] = mb;
// also add all surface decals
R_AddSurfaceDecals( surf );
return mb;
}
/*
=================
R_CullBrushModel
=================
*/
qboolean R_CullBrushModel( ref_entity_t *e )
{
qboolean rotated;
ref_model_t *model = e->model;
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
int i;
if( bmodel->nummodelsurfaces == 0 )
return true;
rotated = !Matrix3x3_Compare( e->axis, matrix3x3_identity );
if( rotated )
{
for( i = 0; i < 3; i++ )
{
modelmins[i] = e->origin[i] - model->radius * e->scale;
modelmaxs[i] = e->origin[i] + model->radius * e->scale;
}
if( R_CullSphere( e->origin, model->radius * e->scale, RI.clipFlags ))
return true;
}
else
{
VectorMA( e->origin, e->scale, model->mins, modelmins );
VectorMA( e->origin, e->scale, model->maxs, modelmaxs );
if( R_CullBox( modelmins, modelmaxs, RI.clipFlags ))
return true;
}
if( RI.rdflags & ( RDF_PORTALINVIEW|RDF_SKYPORTALINVIEW ) || ( RI.params & RP_SKYPORTALVIEW ))
{
if( rotated )
{
if( R_VisCullSphere( e->origin, model->radius * e->scale ))
return true;
}
else
{
if( R_VisCullBox( modelmins, modelmaxs ))
return true;
}
}
return false;
}
void R_BmodelDrawDebug( void )
{
vec3_t bbox[8];
ref_model_t *model;
int i;
if( r_drawentities->integer != 5 )
return;
model = RI.currententity->model;
// compute a full bounding box
for( i = 0; i < 8; i++ )
{
bbox[i][0] = (i & 1) ? model->mins[0] : model->maxs[0];
bbox[i][1] = (i & 2) ? model->mins[1] : model->maxs[1];
bbox[i][2] = (i & 4) ? model->mins[2] : model->maxs[2];
}
R_RotateForEntity( RI.currententity );
pglColor4f( 1.0f, 1.0f, 0.0f, 1.0f ); // yellow bboxes for brushmodels
pglBegin( GL_LINES );
for( i = 0; i < 2; i += 1 )
{
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i+0] );
pglVertex3fv( bbox[i+4] );
pglVertex3fv( bbox[i+2] );
pglVertex3fv( bbox[i+6] );
pglVertex3fv( bbox[i*2+0] );
pglVertex3fv( bbox[i*2+1] );
pglVertex3fv( bbox[i*2+4] );
pglVertex3fv( bbox[i*2+5] );
}
pglEnd();
}
/*
=================
R_AddBrushModelToList
=================
*/
void R_AddBrushModelToList( ref_entity_t *e )
{
qboolean rotated;
uint i, dlightbits;
ref_model_t *model = e->model;
mbrushmodel_t *bmodel = (mbrushmodel_t *)model->extradata;
msurface_t *psurf;
meshbuffer_t *mb;
rotated = !Matrix3x3_Compare( e->axis, matrix3x3_identity );
VectorSubtract( RI.refdef.vieworg, e->origin, modelorg );
if( rotated )
{
vec3_t temp;
VectorCopy( modelorg, temp );
Matrix3x3_Transform( e->axis, temp, modelorg );
}
dlightbits = 0;
if(( r_dynamiclight->integer == 1 ) && !r_fullbright->integer && !( RI.params & RP_SHADOWMAPVIEW ))
{
for( i = 0; i < r_numDlights; i++ )
{
if( BoundsIntersect( modelmins, modelmaxs, r_dlights[i].mins, r_dlights[i].maxs ))
dlightbits |= ( 1<<i );
}
}
for( i = 0, psurf = bmodel->firstmodelsurface; i < bmodel->nummodelsurfaces; i++, psurf++ )
{
if( !R_SurfPotentiallyVisible( psurf ))
continue;
if( RI.params & RP_SHADOWMAPVIEW )
{
if( psurf->visframe != r_framecount )
continue;
if(( psurf->shader->sort >= SORT_OPAQUE ) && ( psurf->shader->sort <= SORT_BANNER ))
{
if( prevRI.surfmbuffers[psurf - r_worldbrushmodel->surfaces] )
{
if( !R_CullSurface( psurf, 0 ))
{
RI.params |= RP_WORLDSURFVISIBLE;
prevRI.surfmbuffers[psurf - r_worldbrushmodel->surfaces]->shadowbits |= RI.shadowGroup->bit;
}
}
}
continue;
}
psurf->visframe = r_framecount;
mb = R_AddSurfaceToList( psurf, 0 );
if( mb )
{
mb->sortkey |= (( psurf->superLightStyle+1 ) << 10 );
if( R_SurfPotentiallyLit( psurf ))
mb->dlightbits = dlightbits;
}
}
}
/*
=============================================================
WORLD MODEL
=============================================================
*/
/*
================
R_RecursiveWorldNode
================
*/
static void R_RecursiveWorldNode( mnode_t *node, uint clipflags, uint dlightbits )
{
const mplane_t *clipplane;
int i, clipped;
uint newDlightbits;
msurface_t **mark, *surf;
mleaf_t *leaf;
meshbuffer_t *mb;
if( node->contents == CONTENTS_SOLID )
return; // hit a solid leaf
if( node->pvsframe != r_pvsframecount )
return; // not visible for this frame
if( clipflags )
{
for( i = 0, clipplane = RI.frustum; i < 6; i++, clipplane++ )
{
if(!( clipflags & ( 1<<i )))
continue;
clipped = BoxOnPlaneSide( node->mins, node->maxs, clipplane );
if( clipped == 2 ) return;
if( clipped == 1 ) clipflags &= ~(1<<i);
}
}
// recurse down the children
if( node->contents == CONTENTS_NODE )
{
newDlightbits = 0;
if( dlightbits )
{
float dist;
for( i = 0; i < r_numDlights; i++ )
{
if(!( dlightbits & ( 1<<i )))
continue;
dist = PlaneDiff( r_dlights[i].origin, node->plane );
if( dist < -r_dlights[i].intensity )
dlightbits &= ~(1<<i);
if( dist < r_dlights[i].intensity )
newDlightbits |= (1<<i);
}
}
R_RecursiveWorldNode( node->children[0], clipflags, dlightbits );
dlightbits = newDlightbits;
R_RecursiveWorldNode( node->children[1], clipflags, dlightbits );
return;
}
// if a leaf node, draw stuff
leaf = (mleaf_t *)node;
leaf->visframe = r_framecount;
if( !leaf->numMarkSurfaces )
return; // nothing to draw
// add leaf bounds to view bounds
for( i = 0; i < 3; i++ )
{
RI.visMins[i] = min( RI.visMins[i], leaf->mins[i] );
RI.visMaxs[i] = max( RI.visMaxs[i], leaf->maxs[i] );
}
// add all the surfaces
for( i = 0, mark = leaf->firstMarkSurface; i < leaf->numMarkSurfaces; i++, mark++ )
{
surf = *mark;
// NOTE: that R_AddSurfaceToList may set meshBuffer to NULL
// for world ALL surfaces to prevent referencing to freed memory region
if( surf->visframe != r_framecount )
{
surf->visframe = r_framecount;
mb = R_AddSurfaceToList( surf, clipflags );
if( mb ) mb->sortkey |= (( surf->superLightStyle+1 ) << 10 );
}
else
{
mb = RI.surfmbuffers[surf - r_worldbrushmodel->surfaces];
}
newDlightbits = mb ? dlightbits & ~mb->dlightbits : 0;
if( newDlightbits && R_SurfPotentiallyLit( surf ))
mb->dlightbits |= R_AddSurfDlighbits( surf, newDlightbits );
}
c_world_leafs++;
}
/*
================
R_MarkShadowLeafSurfaces
================
*/
static void R_MarkShadowLeafSurfaces( msurface_t **mark, uint numfaces, uint clipflags )
{
msurface_t *surf;
meshbuffer_t *mb;
const uint bit = RI.shadowGroup->bit;
int i;
for( i = 0; i < numfaces; i++ )
{
surf = *mark++;
mb = prevRI.surfmbuffers[surf - r_worldbrushmodel->surfaces];
if( !mb || ( mb->shadowbits & bit ))
continue;
// this surface is visible in previous RI, not marked as shadowed...
if(( surf->shader->sort >= SORT_OPAQUE ) && ( surf->shader->sort <= SORT_ALPHATEST ))
{
// ...is opaque
if( !R_CullSurface( surf, clipflags ))
{
// and is visible to the light source too
RI.params |= RP_WORLDSURFVISIBLE;
mb->shadowbits |= bit;
}
}
}
}
/*
================
R_LinearShadowLeafs
================
*/
static void R_LinearShadowLeafs( void )
{
uint i, j, cpf;
const mplane_t *clipplane;
int clipped;
mleaf_t *pleaf;
for( i = 0; i < r_worldbrushmodel->numleafs; i++ )
{
pleaf = &r_worldbrushmodel->leafs[i+1];
if( pleaf->visframe != r_framecount )
continue;
if( !( RI.shadowGroup->vis[i>>3] & ( 1<<( i & 7 ))))
continue;
cpf = RI.clipFlags;
for( j = 0, clipplane = RI.frustum; j < 6; j++, clipplane++ )
{
clipped = BoxOnPlaneSide( pleaf->mins, pleaf->maxs, clipplane );
if( clipped == 2 ) break;
if( clipped == 1 ) cpf &= ~(1<<j);
}
if( !j )
{
R_MarkShadowLeafSurfaces( pleaf->firstMarkSurface, pleaf->numMarkSurfaces, cpf );
c_world_leafs++;
}
}
}
//==================================================================================
int r_surfQueryKeys[MAX_SURF_QUERIES];
/*
===============
R_ClearSurfOcclusionQueryKeys
===============
*/
void R_ClearSurfOcclusionQueryKeys( void )
{
Mem_Set( r_surfQueryKeys, -1, sizeof( r_surfQueryKeys ));
}
/*
===============
R_SurfOcclusionQueryKey
===============
*/
int R_SurfOcclusionQueryKey( ref_entity_t *e, msurface_t *surf )
{
int i;
int *keys = r_surfQueryKeys;
int key = surf - r_worldbrushmodel->surfaces;
if( e != r_worldent )
return -1;
for( i = 0; i < MAX_SURF_QUERIES; i++ )
{
if( keys[i] >= 0 )
{
if( keys[i] == key )
return i;
}
else
{
keys[i] = key;
return i;
}
}
return -1;
}
/*
===============
R_SurfIssueOcclusionQueries
===============
*/
void R_SurfIssueOcclusionQueries( void )
{
int i, *keys = r_surfQueryKeys;
msurface_t *surf;
for( i = 0; keys[i] >= 0; i++ )
{
surf = &r_worldbrushmodel->surfaces[keys[i]];
R_IssueOcclusionQuery( R_GetOcclusionQueryNum( OQ_CUSTOM, i ), r_worldent, surf->mins, surf->maxs );
}
}
//==================================================================================
/*
=============
R_CalcDistancesToFogVolumes
=============
*/
static void R_CalcDistancesToFogVolumes( void )
{
int i;
mfog_t *fog;
for( i = 0, fog = r_worldbrushmodel->fogs; i < r_worldbrushmodel->numfogs; i++, fog++ )
RI.fog_dist_to_eye[fog - r_worldbrushmodel->fogs] = PlaneDiff( RI.viewOrigin, fog->visibleplane );
}
/*
=============
R_DrawWorld
=============
*/
void R_DrawWorld( void )
{
int clipflags;
uint dlightbits;
double starttime;
if( !r_drawworld->integer )
return;
if( !RI.drawWorld ) return;
if( !r_worldmodel || !r_worldbrushmodel )
return;
VectorCopy( RI.refdef.vieworg, modelorg );
RI.previousentity = NULL;
RI.currententity = r_worldent;
RI.currentmodel = RI.currententity->model;
if(!( RI.params & RP_SHADOWMAPVIEW ))
{
R_AllocMeshbufPointers( &RI );
Mem_Set( RI.surfmbuffers, 0, r_worldbrushmodel->numsurfaces * sizeof( meshbuffer_t* ));
R_CalcDistancesToFogVolumes();
}
ClearBounds( RI.visMins, RI.visMaxs );
R_ClearSkyBox();
if( r_nocull->integer ) clipflags = 0;
else clipflags = RI.clipFlags;
if( r_speeds->integer )
starttime = Sys_DoubleTime();
if( r_dynamiclight->integer != 1 || r_fullbright->integer )
dlightbits = 0;
else dlightbits = r_numDlights < 32 ? ( 1 << r_numDlights ) - 1 : -1;
if( RI.params & RP_SHADOWMAPVIEW ) R_LinearShadowLeafs ();
else R_RecursiveWorldNode( r_worldbrushmodel->nodes, clipflags, dlightbits );
if( r_speeds->integer )
r_world_node += Sys_DoubleTime() - starttime;
}
/*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current leaf
===============
*/
void R_MarkLeaves( void )
{
byte *vis;
mleaf_t *leaf;
mnode_t *node;
int i;
if( !RI.drawWorld ) return;
if( RI.params & RP_SHADOWMAPVIEW )
return;
if( r_viewleaf == r_oldviewleaf && r_viewleaf2 == r_oldviewleaf2 && !r_novis->integer && r_viewleaf != NULL )
return;
// development aid to let you run around
// and see exactly where the pvs ends
if( r_lockpvs->integer )
return;
r_pvsframecount++;
r_oldviewleaf = r_viewleaf;
r_oldviewleaf2 = r_viewleaf2;
if( r_novis->integer || r_viewleaf == NULL || !r_worldbrushmodel->visdata )
{
// mark everything
for( i = 0, leaf = r_worldbrushmodel->leafs; i < r_worldbrushmodel->numleafs; i++, leaf++ )
leaf->pvsframe = r_pvsframecount;
for( i = 0, node = r_worldbrushmodel->nodes; i < r_worldbrushmodel->numnodes; i++, node++ )
node->pvsframe = r_pvsframecount;
return;
}
// may have to combine two clusters
// because of solid water boundaries
vis = Mod_LeafPVS( r_viewleaf, r_worldmodel );
if( r_viewleaf != r_viewleaf2 )
{
int longs = (r_worldbrushmodel->numleafs + 31)>>5;
Mem_Copy( fatpvs, vis, longs << 2 );
vis = Mod_LeafPVS( r_viewleaf2, r_worldmodel );
for( i = 0; i < longs; i++ )
((int *)fatpvs)[i] |= ((int *)vis)[i];
vis = fatpvs;
}
for( i = 0; i < r_worldbrushmodel->numleafs-1; i++ ) // FIXME: this is right ?
{
if( vis[i>>3] & ( 1<<( i & 7 )))
{
node = (mnode_t *)&r_worldbrushmodel->leafs[i+1];
do
{
if( node->pvsframe == r_pvsframecount )
break;
node->pvsframe = r_pvsframecount;
node = node->parent;
} while( node );
}
}
}

View File

@ -1,148 +0,0 @@
//=======================================================================
// Copyright XashXT Group 2008 ©
// render_api.h - xash renderer api
//=======================================================================
#ifndef RENDER_API_H
#define RENDER_API_H
#include "ref_params.h"
#define MAP_DEFAULT_SHADER "*black" // engine built-in default shader
// shader types used for shader loading
#define SHADER_SKY 1 // sky box shader
#define SHADER_NOMIP 2 // 2d images
#define SHADER_DECAL 3 // used for decals only
#define SHADER_SPRITE 4 // hud sprites
#define SHADER_GENERIC 5 // generic shader
// dlight flags
#define DLIGHT_ONLYENTS BIT( 0 )
#define DLIGHT_DARK BIT( 1 )
// screenshot types
#define VID_SCREENSHOT 0
#define VID_LEVELSHOT 1
#define VID_MINISHOT 2
typedef struct
{
int numverts;
vec3_t *verts;
vec2_t *stcoords;
rgba_t *colors;
union
{
struct ref_shader_s *shader;
shader_t shadernum;
};
int fognum;
vec3_t normal;
vec3_t lightingOrigin;
} poly_t;
typedef struct
{
vec3_t position;
char name[64]; // same as CS_SIZE
short entityIndex; // FIXME: replace with pointer to entity ?
byte depth;
byte flags;
// this is the surface plane that we hit so that
// we can move certain decals across
// transitions if they hit similar geometry
vec3_t impactPlaneNormal;
} decallist_t;
/*
==============================================================================
RENDER.DLL INTERFACE
==============================================================================
*/
typedef struct render_exp_s
{
// interface validator
size_t api_size; // must matched with sizeof(render_exp_t)
size_t com_size; // must matched with sizeof(stdlib_api_t)
// initialize
qboolean (*Init)( qboolean full ); // init all render systems
void (*Shutdown)( qboolean full ); // shutdown all render systems
void (*BeginRegistration)( const char *map );
qboolean (*RegisterModel)( const char *name, int cl_index ); // also build replacement index table
shader_t (*RegisterShader)( const char *name, int shaderType );
shader_t (*RegisterShaderInt)( const char *name, const byte *image_buf, size_t image_size ); // from memory
void (*EndRegistration)( const char *skyname );
void (*FreeShader)( const char *shadername );
// prepare frame to rendering
qboolean (*AddRefEntity)( struct cl_entity_s *pRefEntity, int entityType, shader_t customShader );
qboolean (*DecalShoot)( shader_t decal, int ent, int model, vec3_t pos, vec3_t saxis, int flags, rgba_t color, float fadeTime, float fadeDuration );
qboolean (*AddDLight)( vec3_t pos, color24 color, float radius, int flags );
qboolean (*AddPolygon)( const poly_t *poly );
qboolean (*AddLightStyle)( int stylenum, vec3_t color );
void (*ClearScene)( void );
void (*BeginFrame)( qboolean clearScene );
void (*RenderFrame)( const ref_params_t *fd, qboolean drawWorld );
void (*EndFrame)( void );
// triapi implementation
void (*RenderMode)( const int mode );
shader_t (*GetSpriteTexture)( int spriteIndex, int spriteFrame );
void (*Normal3f)( const float x, const float y, const float z );
void (*Vertex3f)( const float x, const float y, const float z );
void (*Color4ub)( const byte r, const byte g, const byte b, const byte a );
void (*Fog)( float flFogColor[3], float flStart, float flEnd, int bOn );
void (*TexCoord2f)( const float u, const float v );
void (*Bind)( shader_t shader, int frame );
void (*CullFace)( int mode );
void (*Begin)( int mode );
void (*End)( void );
// misc utilities
void (*SetColor)( const rgba_t color );
void (*SetParms)( shader_t handle, int rendermode, int frame );
void (*GetParms)( int *w, int *h, int *frames, int frame, shader_t shader );
qboolean (*ScrShot)( const char *filename, int shot_type ); // write screenshot with same name
qboolean (*EnvShot)( const char *filename, uint size, const float *vieworg, qboolean skyshot );
void (*SetSkyPortal)( const vec3_t vieworg, const vec3_t viewangles, float scale, float fov );
void (*LightForPoint)( const vec3_t point, vec3_t ambientLight );
void (*DrawStretchRaw)( float x, float y, float w, float h, int cols, int rows, byte *data, qboolean redraw );
void (*DrawStretchPic)( float x, float y, float w, float h, float s1, float t1, float s2, float t2, shader_t shader );
int (*WorldToScreen)( const float *world, float *screen );
void (*ScreenToWorld)( const float *screen, float *world );
qboolean (*CullBox)( const vec3_t mins, const vec3_t maxs );
qboolean (*RSpeedsMessage)( char *out, size_t size );
int (*CreateDecalList)( decallist_t *pList, qboolean changelevel ); // helper to serialize decals
void (*DecalRemoveAll)( shader_t shader );
byte *(*GetCurrentVis)( void );
void (*RestoreGamma)( void );
} render_exp_t;
typedef struct render_imp_s
{
// interface validator
size_t api_size; // must matched with sizeof(render_imp_t)
// client fundamental callbacks
void (*UpdateScreen)( void ); // update screen while loading
void (*StudioEvent)( struct mstudioevent_s *event, struct cl_entity_s *ent );
void (*ShowCollision)( cmdraw_t callback ); // debug
long (*WndProc)( void *hWnd, uint uMsg, uint wParam, long lParam );
struct cl_entity_s *(*GetClientEdict)( int index );
struct player_info_s *(*GetPlayerInfo)( int playerIndex ); // not an entityIndex!!!
struct cl_entity_s *(*GetLocalPlayer)( void );
int (*GetMaxClients)( void );
void (*DrawTriangles)( int fTrans );
qboolean (*IsThirdPerson)( void );
void (*ExtraUpdate)( void ); // call during RenderFrame
float (*GetLerpFrac)( void );
} render_imp_t;
#endif//RENDER_API_H

View File

@ -1,241 +0,0 @@
# Microsoft Developer Studio Project File - Name="vid_gl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=vid_gl - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "vid_gl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "vid_gl.mak" CFG="vid_gl - Win32 Release"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "vid_gl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "vid_gl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "vid_gl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "..\temp\vid_gl\!release"
# PROP Intermediate_Dir "..\temp\vid_gl\!release"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir "."
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "../public" /I "../common" /I "../pm_shared" /I "../engine" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 msvcrt.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /pdb:none /machine:I386 /nodefaultlib:"libc.lib" /libpath:"../public/libs/"
# SUBTRACT LINK32 /debug
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\vid_gl\!release
InputPath=\Xash3D\src_main\temp\vid_gl\!release\vid_gl.dll
SOURCE="$(InputPath)"
"D:\Xash3D\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\vid_gl.dll "D:\Xash3D\vid_gl.dll"
# End Custom Build
!ELSEIF "$(CFG)" == "vid_gl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir "."
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "..\temp\vid_gl\!debug"
# PROP Intermediate_Dir "..\temp\vid_gl\!debug"
# PROP Ignore_Export_Lib 1
# PROP Target_Dir "."
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MDd /W3 /Gm /Gi /GX /ZI /Od /I "../public" /I "../common" /I "../pm_shared" /I "../engine" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /FD /c
# SUBTRACT CPP /YX
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386
# ADD LINK32 msvcrtd.lib user32.lib gdi32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept
# SUBTRACT LINK32 /profile /incremental:no /map
# Begin Custom Build
TargetDir=\Xash3D\src_main\temp\vid_gl\!debug
InputPath=\Xash3D\src_main\temp\vid_gl\!debug\vid_gl.dll
SOURCE="$(InputPath)"
"D:\Xash3D\vid_gl.dll" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
copy $(TargetDir)\vid_gl.dll "D:\Xash3D\vid_gl.dll"
# End Custom Build
!ENDIF
# Begin Target
# Name "vid_gl - Win32 Release"
# Name "vid_gl - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\r_backend.c
# End Source File
# Begin Source File
SOURCE=.\r_bloom.c
# End Source File
# Begin Source File
SOURCE=.\r_cull.c
# End Source File
# Begin Source File
SOURCE=.\r_decals.c
# End Source File
# Begin Source File
SOURCE=.\r_draw.c
# End Source File
# Begin Source File
SOURCE=.\r_image.c
# End Source File
# Begin Source File
SOURCE=.\r_light.c
# End Source File
# Begin Source File
SOURCE=.\r_main.c
# End Source File
# Begin Source File
SOURCE=.\r_math.c
# End Source File
# Begin Source File
SOURCE=.\r_mesh.c
# End Source File
# Begin Source File
SOURCE=.\r_model.c
# End Source File
# Begin Source File
SOURCE=.\r_opengl.c
# End Source File
# Begin Source File
SOURCE=.\r_poly.c
# End Source File
# Begin Source File
SOURCE=.\r_program.c
# End Source File
# Begin Source File
SOURCE=.\r_register.c
# End Source File
# Begin Source File
SOURCE=.\r_shader.c
# End Source File
# Begin Source File
SOURCE=.\r_shadow.c
# End Source File
# Begin Source File
SOURCE=.\r_sky.c
# End Source File
# Begin Source File
SOURCE=.\r_sprite.c
# End Source File
# Begin Source File
SOURCE=.\r_studio.c
# End Source File
# Begin Source File
SOURCE=.\r_surf.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl;fi;fd"
# Begin Source File
SOURCE=.\r_backend.h
# End Source File
# Begin Source File
SOURCE=.\r_local.h
# End Source File
# Begin Source File
SOURCE=.\r_math.h
# End Source File
# Begin Source File
SOURCE=.\r_mesh.h
# End Source File
# Begin Source File
SOURCE=.\r_model.h
# End Source File
# Begin Source File
SOURCE=.\r_opengl.h
# End Source File
# Begin Source File
SOURCE=.\r_public.h
# End Source File
# Begin Source File
SOURCE=.\r_shader.h
# End Source File
# Begin Source File
SOURCE=.\r_shadow.h
# End Source File
# End Group
# End Target
# End Project

View File

@ -1,53 +0,0 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
0.000000, 0.098165, 0.196270, 0.294259, 0.392069, 0.489643, 0.586920, 0.683850,
0.780360, 0.876405, 0.971920, 1.066850, 1.161140, 1.254725, 1.347560, 1.439580,
1.530735, 1.620965, 1.710220, 1.798445, 1.885585, 1.971595, 2.056410, 2.139990,
2.222280, 2.303235, 2.382795, 2.460925, 2.537575, 2.612690, 2.686235, 2.758160,
2.828425, 2.896990, 2.963805, 3.028835, 3.092040, 3.153385, 3.212830, 3.270340,
3.325880, 3.379415, 3.430915, 3.480350, 3.527685, 3.572895, 3.615955, 3.656840,
3.695520, 3.731970, 3.766175, 3.798115, 3.827760, 3.855105, 3.880125, 3.902810,
3.923140, 3.941110, 3.956705, 3.969920, 3.980740, 3.989160, 3.995180, 3.998795,
4.000000, 3.998795, 3.995180, 3.989160, 3.980740, 3.969920, 3.956705, 3.941110,
3.923140, 3.902810, 3.880125, 3.855105, 3.827760, 3.798115, 3.766175, 3.731970,
3.695520, 3.656840, 3.615955, 3.572895, 3.527685, 3.480350, 3.430915, 3.379415,
3.325880, 3.270340, 3.212830, 3.153385, 3.092040, 3.028835, 2.963805, 2.896990,
2.828425, 2.758160, 2.686235, 2.612690, 2.537575, 2.460925, 2.382795, 2.303235,
2.222280, 2.139990, 2.056410, 1.971595, 1.885585, 1.798445, 1.710220, 1.620965,
1.530735, 1.439580, 1.347560, 1.254725, 1.161140, 1.066850, 0.971920, 0.876405,
0.780360, 0.683850, 0.586920, 0.489643, 0.392069, 0.294259, 0.196270, 0.098165,
0.000000, -0.098165, -0.196270, -0.294259, -0.392069, -0.489643, -0.586920, -0.683850,
-0.780360, -0.876405, -0.971920, -1.066850, -1.161140, -1.254725, -1.347560, -1.439580,
-1.530735, -1.620965, -1.710220, -1.798445, -1.885585, -1.971595, -2.056410, -2.139990,
-2.222280, -2.303235, -2.382795, -2.460925, -2.537575, -2.612690, -2.686235, -2.758160,
-2.828425, -2.896990, -2.963805, -3.028835, -3.092040, -3.153385, -3.212830, -3.270340,
-3.325880, -3.379415, -3.430915, -3.480350, -3.527685, -3.572895, -3.615955, -3.656840,
-3.695520, -3.731970, -3.766175, -3.798115, -3.827760, -3.855105, -3.880125, -3.902810,
-3.923140, -3.941110, -3.956705, -3.969920, -3.980740, -3.989160, -3.995180, -3.998795,
-4.000000, -3.998795, -3.995180, -3.989160, -3.980740, -3.969920, -3.956705, -3.941110,
-3.923140, -3.902810, -3.880125, -3.855105, -3.827760, -3.798115, -3.766175, -3.731970,
-3.695520, -3.656840, -3.615955, -3.572895, -3.527685, -3.480350, -3.430915, -3.379415,
-3.325880, -3.270340, -3.212830, -3.153385, -3.092040, -3.028835, -2.963805, -2.896990,
-2.828425, -2.758160, -2.686235, -2.612690, -2.537575, -2.460925, -2.382795, -2.303235,
-2.222280, -2.139990, -2.056410, -1.971595, -1.885585, -1.798445, -1.710220, -1.620965,
-1.530735, -1.439580, -1.347560, -1.254725, -1.161140, -1.066850, -0.971920, -0.876405,
-0.780360, -0.683850, -0.586920, -0.489643, -0.392069, -0.294259, -0.196270, -0.098165,