28 Dec 2010
This commit is contained in:
parent
7143afc284
commit
3b659054d8
|
@ -31,7 +31,6 @@ pm_shared\
|
|||
public\
|
||||
launch\
|
||||
mainui\
|
||||
vid_gl\
|
||||
utils\
|
||||
utils\vgui\
|
||||
utils\vgui\include\
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
107
launch/cvar.c
107
launch/cvar.c
|
@ -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" );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++ )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)" );
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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" )));
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 " );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
3225
vid_gl/r_backend.c
3225
vid_gl/r_backend.c
File diff suppressed because it is too large
Load Diff
|
@ -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__*/
|
524
vid_gl/r_bloom.c
524
vid_gl/r_bloom.c
|
@ -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] );
|
||||
}
|
585
vid_gl/r_cull.c
585
vid_gl/r_cull.c
|
@ -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;
|
||||
}
|
1279
vid_gl/r_decals.c
1279
vid_gl/r_decals.c
File diff suppressed because it is too large
Load Diff
704
vid_gl/r_draw.c
704
vid_gl/r_draw.c
|
@ -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;
|
||||
}
|
||||
}
|
3835
vid_gl/r_image.c
3835
vid_gl/r_image.c
File diff suppressed because it is too large
Load Diff
1209
vid_gl/r_light.c
1209
vid_gl/r_light.c
File diff suppressed because it is too large
Load Diff
873
vid_gl/r_local.h
873
vid_gl/r_local.h
|
@ -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__*/
|
2570
vid_gl/r_main.c
2570
vid_gl/r_main.c
File diff suppressed because it is too large
Load Diff
226
vid_gl/r_math.c
226
vid_gl/r_math.c
|
@ -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 );
|
||||
}
|
|
@ -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__*/
|
1443
vid_gl/r_mesh.c
1443
vid_gl/r_mesh.c
File diff suppressed because it is too large
Load Diff
114
vid_gl/r_mesh.h
114
vid_gl/r_mesh.h
|
@ -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__*/
|
2778
vid_gl/r_model.c
2778
vid_gl/r_model.c
File diff suppressed because it is too large
Load Diff
356
vid_gl/r_model.h
356
vid_gl/r_model.h
|
@ -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
|
|
@ -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 );
|
||||
}
|
1128
vid_gl/r_opengl.h
1128
vid_gl/r_opengl.h
File diff suppressed because it is too large
Load Diff
456
vid_gl/r_poly.c
456
vid_gl/r_poly.c
|
@ -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;
|
||||
}
|
1139
vid_gl/r_program.c
1139
vid_gl/r_program.c
File diff suppressed because it is too large
Load Diff
1123
vid_gl/r_register.c
1123
vid_gl/r_register.c
File diff suppressed because it is too large
Load Diff
4191
vid_gl/r_shader.c
4191
vid_gl/r_shader.c
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__*/
|
652
vid_gl/r_sky.c
652
vid_gl/r_sky.c
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
2694
vid_gl/r_studio.c
2694
vid_gl/r_studio.c
File diff suppressed because it is too large
Load Diff
718
vid_gl/r_surf.c
718
vid_gl/r_surf.c
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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,
|
Reference in New Issue