yquake2remaster/src/refresh/r_main.c

1630 lines
38 KiB
C
Raw Normal View History

/*
* Copyright (C) 1997-2001 Id Software, Inc.
*
2010-10-23 06:58:56 +00:00
* 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.
*
2010-10-23 06:58:56 +00:00
* 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
2010-10-23 06:58:56 +00:00
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
2010-10-23 06:58:56 +00:00
* =======================================================================
*
* Refresher setup and main part of the frame generation
*
* =======================================================================
*/
2009-03-05 12:42:43 +00:00
2009-03-05 11:03:08 +00:00
#include "header/local.h"
#define NUM_BEAM_SEGS 6
void R_Clear ( void );
void R_BeginRegistration ( char *map );
struct model_s *R_RegisterModel ( char *name );
struct image_s *R_RegisterSkin ( char *name );
void R_SetSky ( char *name, float rotate, vec3_t axis );
void R_EndRegistration ( void );
void R_RenderFrame ( refdef_t *fd );
struct image_s *Draw_FindPic ( char *name );
void Draw_Pic ( int x, int y, char *name );
void Draw_Char ( int x, int y, int c );
void Draw_TileClear ( int x, int y, int w, int h, char *name );
void Draw_Fill ( int x, int y, int w, int h, int c );
void Draw_FadeScreen ( void );
viddef_t vid;
refimport_t ri;
int QGL_TEXTURE0, QGL_TEXTURE1;
model_t *r_worldmodel;
float gldepthmin, gldepthmax;
glconfig_t gl_config;
glstate_t gl_state;
image_t *r_notexture; /* use for bad textures */
image_t *r_particletexture; /* little dot for particles */
entity_t *currententity;
model_t *currentmodel;
cplane_t frustum [ 4 ];
int r_visframecount; /* bumped when going to a new PVS */
int r_framecount; /* used for dlight push checking */
int c_brush_polys, c_alias_polys;
float v_blend [ 4 ]; /* final blending color */
void R_Strings ( void );
/* view origin */
vec3_t vup;
vec3_t vpn;
vec3_t vright;
vec3_t r_origin;
float r_world_matrix [ 16 ];
float r_base_world_matrix [ 16 ];
/* screen size info */
refdef_t r_newrefdef;
int r_viewcluster, r_viewcluster2, r_oldviewcluster, r_oldviewcluster2;
extern qboolean have_stencil;
unsigned r_rawpalette [ 256 ];
2010-10-24 08:50:01 +00:00
cvar_t *gl_norefresh;
cvar_t *gl_drawentities;
cvar_t *gl_drawworld;
cvar_t *gl_speeds;
cvar_t *gl_fullbright;
cvar_t *gl_novis;
cvar_t *gl_nocull;
cvar_t *gl_lerpmodels;
cvar_t *gl_lefthand;
2012-03-08 11:24:45 +00:00
cvar_t *gl_farsee;
2010-10-24 08:50:01 +00:00
cvar_t *gl_lightlevel;
2010-10-25 13:21:52 +00:00
cvar_t *gl_overbrightbits;
cvar_t *gl_nosubimage;
cvar_t *gl_allow_software;
cvar_t *gl_vertex_arrays;
cvar_t *gl_particle_min_size;
cvar_t *gl_particle_max_size;
cvar_t *gl_particle_size;
cvar_t *gl_particle_att_a;
cvar_t *gl_particle_att_b;
cvar_t *gl_particle_att_c;
cvar_t *gl_ext_swapinterval;
cvar_t *gl_ext_palettedtexture;
cvar_t *gl_ext_multitexture;
cvar_t *gl_ext_pointparameters;
cvar_t *gl_ext_compiled_vertex_array;
2010-10-25 13:21:52 +00:00
cvar_t *gl_ext_mtexcombine;
cvar_t *gl_log;
cvar_t *gl_bitdepth;
cvar_t *gl_drawbuffer;
cvar_t *gl_driver;
cvar_t *gl_lightmap;
cvar_t *gl_shadows;
cvar_t *gl_stencilshadow;
cvar_t *gl_mode;
cvar_t *gl_customwidth;
cvar_t *gl_customheight;
#ifdef RETEXTURE
cvar_t *gl_retexturing;
#endif
cvar_t *gl_dynamic;
cvar_t *gl_modulate;
cvar_t *gl_nobind;
cvar_t *gl_round_down;
cvar_t *gl_picmip;
cvar_t *gl_skymip;
cvar_t *gl_showtris;
cvar_t *gl_ztrick;
cvar_t *gl_finish;
cvar_t *gl_clear;
cvar_t *gl_cull;
cvar_t *gl_polyblend;
cvar_t *gl_flashblend;
cvar_t *gl_playermip;
cvar_t *gl_saturatelighting;
cvar_t *gl_swapinterval;
cvar_t *gl_texturemode;
cvar_t *gl_texturealphamode;
cvar_t *gl_texturesolidmode;
2011-10-17 10:43:48 +00:00
cvar_t *gl_anisotropic;
cvar_t *gl_anisotropic_avail;
cvar_t *gl_lockpvs;
cvar_t *vid_fullscreen;
cvar_t *vid_gamma;
cvar_t *vid_ref;
/*
* Returns true if the box is completely outside the frustom
*/
qboolean
R_CullBox ( vec3_t mins, vec3_t maxs )
{
int i;
2010-10-24 08:50:01 +00:00
if ( gl_nocull->value )
{
return ( false );
}
for ( i = 0; i < 4; i++ )
{
if ( BOX_ON_PLANE_SIDE( mins, maxs, &frustum [ i ] ) == 2 )
{
return ( true );
}
}
return ( false );
}
void
R_RotateForEntity ( entity_t *e )
{
qglTranslatef( e->origin [ 0 ], e->origin [ 1 ], e->origin [ 2 ] );
qglRotatef( e->angles [ 1 ], 0, 0, 1 );
qglRotatef( -e->angles [ 0 ], 0, 1, 0 );
qglRotatef( -e->angles [ 2 ], 1, 0, 0 );
}
void
R_DrawSpriteModel ( entity_t *e )
{
float alpha = 1.0F;
vec3_t point;
dsprframe_t *frame;
float *up, *right;
dsprite_t *psprite;
/* don't even bother culling, because it's just a single
* polygon without a surface cache */
psprite = (dsprite_t *) currentmodel->extradata;
e->frame %= psprite->numframes;
frame = &psprite->frames [ e->frame ];
{
/* normal sprite */
up = vup;
right = vright;
}
if ( e->flags & RF_TRANSLUCENT )
{
alpha = e->alpha;
}
if ( alpha != 1.0F )
{
qglEnable( GL_BLEND );
}
qglColor4f( 1, 1, 1, alpha );
R_Bind( currentmodel->skins [ e->frame ]->texnum );
R_TexEnv( GL_MODULATE );
if ( alpha == 1.0 )
{
qglEnable( GL_ALPHA_TEST );
}
else
{
qglDisable( GL_ALPHA_TEST );
}
qglBegin( GL_QUADS );
qglTexCoord2f( 0, 1 );
VectorMA( e->origin, -frame->origin_y, up, point );
VectorMA( point, -frame->origin_x, right, point );
qglVertex3fv( point );
qglTexCoord2f( 0, 0 );
VectorMA( e->origin, frame->height - frame->origin_y, up, point );
VectorMA( point, -frame->origin_x, right, point );
qglVertex3fv( point );
qglTexCoord2f( 1, 0 );
VectorMA( e->origin, frame->height - frame->origin_y, up, point );
VectorMA( point, frame->width - frame->origin_x, right, point );
qglVertex3fv( point );
qglTexCoord2f( 1, 1 );
VectorMA( e->origin, -frame->origin_y, up, point );
VectorMA( point, frame->width - frame->origin_x, right, point );
qglVertex3fv( point );
qglEnd();
qglDisable( GL_ALPHA_TEST );
R_TexEnv( GL_REPLACE );
if ( alpha != 1.0F )
{
qglDisable( GL_BLEND );
}
qglColor4f( 1, 1, 1, 1 );
}
void
R_DrawNullModel ( void )
{
vec3_t shadelight;
int i;
if ( currententity->flags & RF_FULLBRIGHT )
{
shadelight [ 0 ] = shadelight [ 1 ] = shadelight [ 2 ] = 1.0F;
}
else
{
R_LightPoint( currententity->origin, shadelight );
}
qglPushMatrix();
R_RotateForEntity( currententity );
qglDisable( GL_TEXTURE_2D );
qglColor3fv( shadelight );
qglBegin( GL_TRIANGLE_FAN );
qglVertex3f( 0, 0, -16 );
for ( i = 0; i <= 4; i++ )
{
qglVertex3f( 16 * cos( i * M_PI / 2 ), 16 * sin( i * M_PI / 2 ), 0 );
}
qglEnd();
qglBegin( GL_TRIANGLE_FAN );
qglVertex3f( 0, 0, 16 );
for ( i = 4; i >= 0; i-- )
{
qglVertex3f( 16 * cos( i * M_PI / 2 ), 16 * sin( i * M_PI / 2 ), 0 );
}
qglEnd();
qglColor3f( 1, 1, 1 );
qglPopMatrix();
qglEnable( GL_TEXTURE_2D );
}
void
R_DrawEntitiesOnList ( void )
{
int i;
2010-10-24 08:50:01 +00:00
if ( !gl_drawentities->value )
{
return;
}
/* draw non-transparent first */
for ( i = 0; i < r_newrefdef.num_entities; i++ )
{
currententity = &r_newrefdef.entities [ i ];
if ( currententity->flags & RF_TRANSLUCENT )
{
continue; /* solid */
}
if ( currententity->flags & RF_BEAM )
{
R_DrawBeam( currententity );
}
else
{
currentmodel = currententity->model;
if ( !currentmodel )
{
R_DrawNullModel();
continue;
}
switch ( currentmodel->type )
{
case mod_alias:
R_DrawAliasModel( currententity );
break;
case mod_brush:
R_DrawBrushModel( currententity );
break;
case mod_sprite:
R_DrawSpriteModel( currententity );
break;
default:
ri.Sys_Error( ERR_DROP, "Bad modeltype" );
break;
}
}
}
/* draw transparent entities
* we could sort these if it ever
* becomes a problem... */
qglDepthMask( 0 ); /* no z writes */
for ( i = 0; i < r_newrefdef.num_entities; i++ )
{
currententity = &r_newrefdef.entities [ i ];
if ( !( currententity->flags & RF_TRANSLUCENT ) )
{
continue; /* solid */
}
if ( currententity->flags & RF_BEAM )
{
R_DrawBeam( currententity );
}
else
{
currentmodel = currententity->model;
if ( !currentmodel )
{
R_DrawNullModel();
continue;
}
switch ( currentmodel->type )
{
case mod_alias:
R_DrawAliasModel( currententity );
break;
case mod_brush:
R_DrawBrushModel( currententity );
break;
case mod_sprite:
R_DrawSpriteModel( currententity );
break;
default:
ri.Sys_Error( ERR_DROP, "Bad modeltype" );
break;
}
}
}
qglDepthMask( 1 ); /* back to writing */
}
void
R_DrawParticles2 ( int num_particles, const particle_t particles[], const unsigned colortable [ 768 ] )
{
const particle_t *p;
int i;
vec3_t up, right;
float scale;
byte color [ 4 ];
R_Bind( r_particletexture->texnum );
qglDepthMask( GL_FALSE ); /* no z buffering */
qglEnable( GL_BLEND );
R_TexEnv( GL_MODULATE );
qglBegin( GL_TRIANGLES );
VectorScale( vup, 1.5, up );
VectorScale( vright, 1.5, right );
for ( p = particles, i = 0; i < num_particles; i++, p++ )
{
/* hack a scale up to keep particles from disapearing */
scale = ( p->origin [ 0 ] - r_origin [ 0 ] ) * vpn [ 0 ] +
( p->origin [ 1 ] - r_origin [ 1 ] ) * vpn [ 1 ] +
( p->origin [ 2 ] - r_origin [ 2 ] ) * vpn [ 2 ];
if ( scale < 20 )
{
scale = 1;
}
else
{
scale = 1 + scale * 0.004;
}
*(int *) color = colortable [ p->color ];
color [ 3 ] = p->alpha * 255;
qglColor4ubv( color );
qglTexCoord2f( 0.0625, 0.0625 );
qglVertex3fv( p->origin );
qglTexCoord2f( 1.0625, 0.0625 );
qglVertex3f( p->origin [ 0 ] + up [ 0 ] * scale,
p->origin [ 1 ] + up [ 1 ] * scale,
p->origin [ 2 ] + up [ 2 ] * scale );
qglTexCoord2f( 0.0625, 1.0625 );
qglVertex3f( p->origin [ 0 ] + right [ 0 ] * scale,
p->origin [ 1 ] + right [ 1 ] * scale,
p->origin [ 2 ] + right [ 2 ] * scale );
}
qglEnd();
qglDisable( GL_BLEND );
qglColor4f( 1, 1, 1, 1 );
qglDepthMask( 1 ); /* back to normal Z buffering */
R_TexEnv( GL_REPLACE );
}
void
R_DrawParticles ( void )
{
if ( gl_ext_pointparameters->value && qglPointParameterfEXT )
{
int i;
unsigned char color [ 4 ];
const particle_t *p;
qglDepthMask( GL_FALSE );
qglEnable( GL_BLEND );
qglDisable( GL_TEXTURE_2D );
qglPointSize( LittleFloat(gl_particle_size->value) );
qglBegin( GL_POINTS );
for ( i = 0, p = r_newrefdef.particles; i < r_newrefdef.num_particles; i++, p++ )
{
*(int *) color = d_8to24table [ p->color & 0xFF ];
color [ 3 ] = p->alpha * 255;
qglColor4ubv( color );
qglVertex3fv( p->origin );
}
qglEnd();
qglDisable( GL_BLEND );
qglColor4f( 1.0F, 1.0F, 1.0F, 1.0F );
qglDepthMask( GL_TRUE );
qglEnable( GL_TEXTURE_2D );
}
else
{
R_DrawParticles2( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table );
}
}
void
R_PolyBlend ( void )
{
if ( !gl_polyblend->value )
{
return;
}
if ( !v_blend [ 3 ] )
{
return;
}
qglDisable( GL_ALPHA_TEST );
qglEnable( GL_BLEND );
qglDisable( GL_DEPTH_TEST );
qglDisable( GL_TEXTURE_2D );
qglLoadIdentity();
qglRotatef( -90, 1, 0, 0 ); /* put Z going up */
qglRotatef( 90, 0, 0, 1 ); /* put Z going up */
qglColor4fv( v_blend );
qglBegin( GL_QUADS );
qglVertex3f( 10, 100, 100 );
qglVertex3f( 10, -100, 100 );
qglVertex3f( 10, -100, -100 );
qglVertex3f( 10, 100, -100 );
qglEnd();
qglDisable( GL_BLEND );
qglEnable( GL_TEXTURE_2D );
qglEnable( GL_ALPHA_TEST );
qglColor4f( 1, 1, 1, 1 );
}
int
R_SignbitsForPlane ( cplane_t *out )
{
int bits, j;
/* for fast box on planeside test */
bits = 0;
for ( j = 0; j < 3; j++ )
{
if ( out->normal [ j ] < 0 )
{
bits |= 1 << j;
}
}
return ( bits );
}
void
R_SetFrustum ( void )
{
int i;
/* rotate VPN right by FOV_X/2 degrees */
RotatePointAroundVector( frustum [ 0 ].normal, vup, vpn, -( 90 - r_newrefdef.fov_x / 2 ) );
/* rotate VPN left by FOV_X/2 degrees */
RotatePointAroundVector( frustum [ 1 ].normal, vup, vpn, 90 - r_newrefdef.fov_x / 2 );
/* rotate VPN up by FOV_X/2 degrees */
RotatePointAroundVector( frustum [ 2 ].normal, vright, vpn, 90 - r_newrefdef.fov_y / 2 );
/* rotate VPN down by FOV_X/2 degrees */
RotatePointAroundVector( frustum [ 3 ].normal, vright, vpn, -( 90 - r_newrefdef.fov_y / 2 ) );
for ( i = 0; i < 4; i++ )
{
frustum [ i ].type = PLANE_ANYZ;
frustum [ i ].dist = DotProduct( r_origin, frustum [ i ].normal );
frustum [ i ].signbits = R_SignbitsForPlane( &frustum [ i ] );
}
}
void
R_SetupFrame ( void )
{
int i;
mleaf_t *leaf;
r_framecount++;
/* build the transformation matrix for the given view angles */
VectorCopy( r_newrefdef.vieworg, r_origin );
AngleVectors( r_newrefdef.viewangles, vpn, vright, vup );
/* current viewcluster */
if ( !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
{
r_oldviewcluster = r_viewcluster;
r_oldviewcluster2 = r_viewcluster2;
leaf = Mod_PointInLeaf( r_origin, r_worldmodel );
r_viewcluster = r_viewcluster2 = leaf->cluster;
/* check above and below so crossing solid water doesn't draw wrong */
if ( !leaf->contents )
{ /* look down a bit */
vec3_t temp;
VectorCopy( r_origin, temp );
temp [ 2 ] -= 16;
leaf = Mod_PointInLeaf( temp, r_worldmodel );
if ( !( leaf->contents & CONTENTS_SOLID ) &&
( leaf->cluster != r_viewcluster2 ) )
{
r_viewcluster2 = leaf->cluster;
}
}
else
{
/* look up a bit */
vec3_t temp;
VectorCopy( r_origin, temp );
temp [ 2 ] += 16;
leaf = Mod_PointInLeaf( temp, r_worldmodel );
if ( !( leaf->contents & CONTENTS_SOLID ) &&
( leaf->cluster != r_viewcluster2 ) )
{
r_viewcluster2 = leaf->cluster;
}
}
}
for ( i = 0; i < 4; i++ )
{
v_blend [ i ] = r_newrefdef.blend [ i ];
}
c_brush_polys = 0;
c_alias_polys = 0;
/* clear out the portion of the screen that the NOWORLDMODEL defines */
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
{
qglEnable( GL_SCISSOR_TEST );
qglClearColor( 0.3, 0.3, 0.3, 1 );
qglScissor( r_newrefdef.x, vid.height - r_newrefdef.height - r_newrefdef.y, r_newrefdef.width, r_newrefdef.height );
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
qglClearColor( 1, 0, 0.5, 0.5 );
qglDisable( GL_SCISSOR_TEST );
}
}
void
R_MYgluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar )
{
GLdouble xmin, xmax, ymin, ymax;
ymax = zNear * tan( fovy * M_PI / 360.0 );
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
xmin += -( 2 * gl_state.camera_separation ) / zNear;
xmax += -( 2 * gl_state.camera_separation ) / zNear;
qglFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
}
void
R_SetupGL ( void )
{
float screenaspect;
int x, x2, y2, y, w, h;
/* set up viewport */
x = floor( r_newrefdef.x * vid.width / vid.width );
x2 = ceil( ( r_newrefdef.x + r_newrefdef.width ) * vid.width / vid.width );
y = floor( vid.height - r_newrefdef.y * vid.height / vid.height );
y2 = ceil( vid.height - ( r_newrefdef.y + r_newrefdef.height ) * vid.height / vid.height );
w = x2 - x;
h = y - y2;
qglViewport( x, y2, w, h );
/* set up projection matrix */
screenaspect = (float) r_newrefdef.width / r_newrefdef.height;
qglMatrixMode( GL_PROJECTION );
qglLoadIdentity();
2012-03-08 11:24:45 +00:00
if (gl_farsee->value == 0) {
R_MYgluPerspective( r_newrefdef.fov_y, screenaspect, 4, 4096 );
} else {
R_MYgluPerspective( r_newrefdef.fov_y, screenaspect, 4, 8192 );
}
qglCullFace( GL_FRONT );
qglMatrixMode( GL_MODELVIEW );
qglLoadIdentity();
qglRotatef( -90, 1, 0, 0 ); /* put Z going up */
qglRotatef( 90, 0, 0, 1 ); /* put Z going up */
qglRotatef( -r_newrefdef.viewangles [ 2 ], 1, 0, 0 );
qglRotatef( -r_newrefdef.viewangles [ 0 ], 0, 1, 0 );
qglRotatef( -r_newrefdef.viewangles [ 1 ], 0, 0, 1 );
qglTranslatef( -r_newrefdef.vieworg [ 0 ], -r_newrefdef.vieworg [ 1 ], -r_newrefdef.vieworg [ 2 ] );
qglGetFloatv( GL_MODELVIEW_MATRIX, r_world_matrix );
/* set drawing parms */
if ( gl_cull->value )
{
qglEnable( GL_CULL_FACE );
}
else
{
qglDisable( GL_CULL_FACE );
}
qglDisable( GL_BLEND );
qglDisable( GL_ALPHA_TEST );
qglEnable( GL_DEPTH_TEST );
}
void
R_Clear ( void )
{
if ( gl_ztrick->value )
{
static int trickframe;
if ( gl_clear->value )
{
qglClear( GL_COLOR_BUFFER_BIT );
}
trickframe++;
if ( trickframe & 1 )
{
gldepthmin = 0;
gldepthmax = 0.49999;
qglDepthFunc( GL_LEQUAL );
}
else
{
gldepthmin = 1;
gldepthmax = 0.5;
qglDepthFunc( GL_GEQUAL );
}
}
else
{
if ( gl_clear->value )
{
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
}
else
{
qglClear( GL_DEPTH_BUFFER_BIT );
}
gldepthmin = 0;
gldepthmax = 1;
qglDepthFunc( GL_LEQUAL );
}
qglDepthRange( gldepthmin, gldepthmax );
/* stencilbuffer shadows */
if ( gl_shadows->value && have_stencil && gl_stencilshadow->value )
{
qglClearStencil( 1 );
qglClear( GL_STENCIL_BUFFER_BIT );
}
}
void
R_Flash ( void )
{
R_PolyBlend();
}
/*
* r_newrefdef must be set before the first call
*/
void
R_RenderView ( refdef_t *fd )
{
2010-10-24 08:50:01 +00:00
if ( gl_norefresh->value )
{
return;
}
r_newrefdef = *fd;
if ( !r_worldmodel && !( r_newrefdef.rdflags & RDF_NOWORLDMODEL ) )
{
ri.Sys_Error( ERR_DROP, "R_RenderView: NULL worldmodel" );
}
2010-10-24 08:50:01 +00:00
if ( gl_speeds->value )
{
c_brush_polys = 0;
c_alias_polys = 0;
}
R_PushDlights();
if ( gl_finish->value )
{
qglFinish();
}
R_SetupFrame();
R_SetFrustum();
R_SetupGL();
R_MarkLeaves(); /* done here so we know if we're in water */
R_DrawWorld();
R_DrawEntitiesOnList();
R_RenderDlights();
R_DrawParticles();
R_DrawAlphaSurfaces();
R_Flash();
2010-10-24 08:50:01 +00:00
if ( gl_speeds->value )
{
ri.Con_Printf( PRINT_ALL, "%4i wpoly %4i epoly %i tex %i lmaps\n",
c_brush_polys,
c_alias_polys,
c_visible_textures,
c_visible_lightmaps );
}
}
void
R_SetGL2D ( void )
{
/* set 2D virtual screen size */
qglViewport( 0, 0, vid.width, vid.height );
qglMatrixMode( GL_PROJECTION );
qglLoadIdentity();
qglOrtho( 0, vid.width, vid.height, 0, -99999, 99999 );
qglMatrixMode( GL_MODELVIEW );
qglLoadIdentity();
qglDisable( GL_DEPTH_TEST );
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
qglEnable( GL_ALPHA_TEST );
qglColor4f( 1, 1, 1, 1 );
}
void
R_SetLightLevel ( void )
{
vec3_t shadelight;
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
{
return;
}
/* save off light value for server to look at */
R_LightPoint( r_newrefdef.vieworg, shadelight );
/* pick the greatest component, which should be the same
* as the mono value returned by software */
if ( shadelight [ 0 ] > shadelight [ 1 ] )
{
if ( shadelight [ 0 ] > shadelight [ 2 ] )
{
2010-10-24 08:50:01 +00:00
gl_lightlevel->value = 150 * shadelight [ 0 ];
}
else
{
2010-10-24 08:50:01 +00:00
gl_lightlevel->value = 150 * shadelight [ 2 ];
}
}
else
{
if ( shadelight [ 1 ] > shadelight [ 2 ] )
{
2010-10-24 08:50:01 +00:00
gl_lightlevel->value = 150 * shadelight [ 1 ];
}
else
{
2010-10-24 08:50:01 +00:00
gl_lightlevel->value = 150 * shadelight [ 2 ];
}
}
}
void
R_RenderFrame ( refdef_t *fd )
{
R_RenderView( fd );
R_SetLightLevel();
R_SetGL2D();
}
void
R_Register ( void )
{
gl_lefthand = ri.Cvar_Get( "hand", "0", CVAR_USERINFO | CVAR_ARCHIVE );
2012-03-08 11:24:45 +00:00
gl_farsee = ri.Cvar_Get( "gl_farsee", "0", CVAR_LATCH | CVAR_ARCHIVE );
2010-10-24 08:50:01 +00:00
gl_norefresh = ri.Cvar_Get( "gl_norefresh", "0", 0 );
gl_fullbright = ri.Cvar_Get( "gl_fullbright", "0", 0 );
gl_drawentities = ri.Cvar_Get( "gl_drawentities", "1", 0 );
gl_drawworld = ri.Cvar_Get( "gl_drawworld", "1", 0 );
gl_novis = ri.Cvar_Get( "gl_novis", "0", 0 );
gl_nocull = ri.Cvar_Get( "gl_nocull", "0", 0 );
gl_lerpmodels = ri.Cvar_Get( "gl_lerpmodels", "1", 0 );
gl_speeds = ri.Cvar_Get( "gl_speeds", "0", 0 );
gl_lightlevel = ri.Cvar_Get( "gl_lightlevel", "0", 0 );
2010-10-25 13:21:52 +00:00
gl_overbrightbits = ri.Cvar_Get( "gl_overbrightbits", "2", CVAR_ARCHIVE );
gl_nosubimage = ri.Cvar_Get( "gl_nosubimage", "0", 0 );
gl_allow_software = ri.Cvar_Get( "gl_allow_software", "0", 0 );
gl_particle_min_size = ri.Cvar_Get( "gl_particle_min_size", "2", CVAR_ARCHIVE );
gl_particle_max_size = ri.Cvar_Get( "gl_particle_max_size", "40", CVAR_ARCHIVE );
gl_particle_size = ri.Cvar_Get( "gl_particle_size", "40", CVAR_ARCHIVE );
gl_particle_att_a = ri.Cvar_Get( "gl_particle_att_a", "0.01", CVAR_ARCHIVE );
gl_particle_att_b = ri.Cvar_Get( "gl_particle_att_b", "0.0", CVAR_ARCHIVE );
gl_particle_att_c = ri.Cvar_Get( "gl_particle_att_c", "0.01", CVAR_ARCHIVE );
gl_modulate = ri.Cvar_Get( "gl_modulate", "1", CVAR_ARCHIVE );
gl_log = ri.Cvar_Get( "gl_log", "0", 0 );
gl_bitdepth = ri.Cvar_Get( "gl_bitdepth", "0", 0 );
gl_mode = ri.Cvar_Get( "gl_mode", "4", CVAR_ARCHIVE );
gl_lightmap = ri.Cvar_Get( "gl_lightmap", "0", 0 );
gl_shadows = ri.Cvar_Get( "gl_shadows", "0", CVAR_ARCHIVE );
gl_stencilshadow = ri.Cvar_Get( "gl_stencilshadow", "0", CVAR_ARCHIVE );
gl_dynamic = ri.Cvar_Get( "gl_dynamic", "1", 0 );
gl_nobind = ri.Cvar_Get( "gl_nobind", "0", 0 );
gl_round_down = ri.Cvar_Get( "gl_round_down", "1", 0 );
gl_picmip = ri.Cvar_Get( "gl_picmip", "0", 0 );
gl_skymip = ri.Cvar_Get( "gl_skymip", "0", 0 );
gl_showtris = ri.Cvar_Get( "gl_showtris", "0", 0 );
gl_ztrick = ri.Cvar_Get( "gl_ztrick", "0", 0 );
gl_finish = ri.Cvar_Get( "gl_finish", "0", CVAR_ARCHIVE );
gl_clear = ri.Cvar_Get( "gl_clear", "0", 0 );
gl_cull = ri.Cvar_Get( "gl_cull", "1", 0 );
gl_polyblend = ri.Cvar_Get( "gl_polyblend", "1", 0 );
gl_flashblend = ri.Cvar_Get( "gl_flashblend", "0", 0 );
gl_playermip = ri.Cvar_Get( "gl_playermip", "0", 0 );
gl_driver = ri.Cvar_Get( "gl_driver", "libGL.so.1", CVAR_ARCHIVE );
gl_texturemode = ri.Cvar_Get( "gl_texturemode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE );
gl_texturealphamode = ri.Cvar_Get( "gl_texturealphamode", "default", CVAR_ARCHIVE );
gl_texturesolidmode = ri.Cvar_Get( "gl_texturesolidmode", "default", CVAR_ARCHIVE );
2011-10-17 10:43:48 +00:00
gl_anisotropic = ri.Cvar_Get( "gl_anisotropic", "0", CVAR_ARCHIVE );
gl_anisotropic_avail = ri.Cvar_Get( "gl_anisotropic_avail", "0", 0 );
gl_lockpvs = ri.Cvar_Get( "gl_lockpvs", "0", 0 );
gl_vertex_arrays = ri.Cvar_Get( "gl_vertex_arrays", "0", CVAR_ARCHIVE );
gl_ext_swapinterval = ri.Cvar_Get( "gl_ext_swapinterval", "1", CVAR_ARCHIVE );
gl_ext_palettedtexture = ri.Cvar_Get( "gl_ext_palettedtexture", "0", CVAR_ARCHIVE );
gl_ext_multitexture = ri.Cvar_Get( "gl_ext_multitexture", "1", CVAR_ARCHIVE );
gl_ext_pointparameters = ri.Cvar_Get( "gl_ext_pointparameters", "1", CVAR_ARCHIVE );
gl_ext_compiled_vertex_array = ri.Cvar_Get( "gl_ext_compiled_vertex_array", "1", CVAR_ARCHIVE );
2010-10-25 13:21:52 +00:00
gl_ext_mtexcombine = ri.Cvar_Get( "gl_ext_mtexcombine", "1", CVAR_ARCHIVE );
gl_drawbuffer = ri.Cvar_Get( "gl_drawbuffer", "GL_BACK", 0 );
gl_swapinterval = ri.Cvar_Get( "gl_swapinterval", "1", CVAR_ARCHIVE );
gl_saturatelighting = ri.Cvar_Get( "gl_saturatelighting", "0", 0 );
vid_fullscreen = ri.Cvar_Get( "vid_fullscreen", "0", CVAR_ARCHIVE );
vid_gamma = ri.Cvar_Get( "vid_gamma", "1.0", CVAR_ARCHIVE );
vid_ref = ri.Cvar_Get( "vid_ref", "soft", CVAR_ARCHIVE );
gl_customwidth = ri.Cvar_Get( "gl_customwidth", "1024", CVAR_ARCHIVE );
gl_customheight = ri.Cvar_Get( "gl_customheight", "768", CVAR_ARCHIVE );
2010-05-22 06:58:09 +00:00
#ifdef RETEXTURE
gl_retexturing = ri.Cvar_Get( "gl_retexturing", "1", CVAR_ARCHIVE );
#endif
ri.Cmd_AddCommand( "imagelist", R_ImageList_f );
ri.Cmd_AddCommand( "screenshot", R_ScreenShot );
ri.Cmd_AddCommand( "modellist", Mod_Modellist_f );
ri.Cmd_AddCommand( "gl_strings", R_Strings );
}
qboolean
R_SetMode ( void )
{
rserr_t err;
qboolean fullscreen;
fullscreen = vid_fullscreen->value;
vid_fullscreen->modified = false;
gl_mode->modified = false;
/* a bit hackish approach to enable custom resolutions:
* Glimp_SetMode needs these values set for mode -1 */
vid.width = gl_customwidth->value;
vid.height = gl_customheight->value;
if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, fullscreen ) ) == rserr_ok )
{
if ( gl_mode->value == -1 )
{
gl_state.prev_mode = 3; /* safe default for custom mode */
}
else
{
gl_state.prev_mode = gl_mode->value;
}
}
else
{
if ( err == rserr_invalid_fullscreen )
{
ri.Cvar_SetValue( "vid_fullscreen", 0 );
vid_fullscreen->modified = false;
ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - fullscreen unavailable in this mode\n" );
if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_mode->value, false ) ) == rserr_ok )
{
return ( true );
}
}
else if ( err == rserr_invalid_mode )
{
ri.Cvar_SetValue( "gl_mode", gl_state.prev_mode );
gl_mode->modified = false;
ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - invalid mode\n" );
}
/* try setting it back to something safe */
if ( ( err = GLimp_SetMode( &vid.width, &vid.height, gl_state.prev_mode, false ) ) != rserr_ok )
{
ri.Con_Printf( PRINT_ALL, "ref_gl::R_SetMode() - could not revert to safe mode\n" );
return ( false );
}
}
return ( true );
}
int
R_Init ( void *hinstance, void *hWnd )
{
char renderer_buffer [ 1000 ];
char vendor_buffer [ 1000 ];
int err;
int j;
extern float r_turbsin [ 256 ];
for ( j = 0; j < 256; j++ )
{
r_turbsin [ j ] *= 0.5;
}
2012-04-25 09:50:06 +00:00
/* Options */
Com_Printf("Refresher build options:\n");
#ifdef RETEXTURE
Com_Printf(" + Retexturing support\n");
#else
Com_Printf(" - Retexturing support\n");
#endif
2012-04-28 20:04:24 +00:00
#ifdef X11GAMMA
2012-04-25 09:50:06 +00:00
Com_Printf(" + Gamma via X11\n");
#else
Com_Printf(" - Gamma via X11\n");
#endif
ri.Con_Printf( PRINT_ALL, "Refresh: " REF_VERSION "\n" );
Draw_GetPalette();
R_Register();
/* initialize our QGL dynamic bindings */
if ( !QGL_Init( gl_driver->string ) )
{
QGL_Shutdown();
ri.Con_Printf( PRINT_ALL, "ref_gl::R_Init() - could not load \"%s\"\n", gl_driver->string );
return ( -1 );
}
/* initialize OS-specific parts of OpenGL */
2010-10-19 12:43:11 +00:00
if ( !GLimp_Init() )
{
QGL_Shutdown();
return ( -1 );
}
/* set our "safe" modes */
gl_state.prev_mode = 3;
/* create the window and set up the context */
if ( !R_SetMode() )
{
QGL_Shutdown();
ri.Con_Printf( PRINT_ALL, "ref_gl::R_Init() - could not R_SetMode()\n" );
return ( -1 );
}
ri.Vid_MenuInit();
/* get our various GL strings */
ri.Con_Printf( PRINT_ALL, "\nOpenGL setting:\n", gl_config.vendor_string );
gl_config.vendor_string = (char *) qglGetString( GL_VENDOR );
ri.Con_Printf( PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
gl_config.renderer_string = (char *) qglGetString( GL_RENDERER );
ri.Con_Printf( PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
gl_config.version_string = (char *) qglGetString( GL_VERSION );
ri.Con_Printf( PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
gl_config.extensions_string = (char *) qglGetString( GL_EXTENSIONS );
ri.Con_Printf( PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
strncpy( renderer_buffer, gl_config.renderer_string, sizeof ( renderer_buffer ) );
renderer_buffer [ sizeof ( renderer_buffer ) - 1 ] = 0;
strlwr( renderer_buffer );
strncpy( vendor_buffer, gl_config.vendor_string, sizeof ( vendor_buffer ) );
vendor_buffer [ sizeof ( vendor_buffer ) - 1 ] = 0;
strlwr( vendor_buffer );
ri.Cvar_Set( "scr_drawall", "0" );
gl_config.allow_cds = true;
2010-10-25 13:21:52 +00:00
ri.Con_Printf( PRINT_ALL, "\n\nProbing for OpenGL extensions:\n" );
/* grab extensions */
if ( strstr( gl_config.extensions_string, "GL_EXT_compiled_vertex_array" ) ||
strstr( gl_config.extensions_string, "GL_SGI_compiled_vertex_array" ) )
{
ri.Con_Printf( PRINT_ALL, "...enabling GL_EXT_compiled_vertex_array\n" );
qglLockArraysEXT = (void *) qwglGetProcAddress( "glLockArraysEXT" );
qglUnlockArraysEXT = (void *) qwglGetProcAddress( "glUnlockArraysEXT" );
}
else
{
ri.Con_Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
if ( strstr( gl_config.extensions_string, "GL_EXT_point_parameters" ) )
{
if ( gl_ext_pointparameters->value )
{
qglPointParameterfEXT = ( void (APIENTRY *) ( GLenum, GLfloat ) )qwglGetProcAddress( "glPointParameterfEXT" );
qglPointParameterfvEXT = ( void (APIENTRY *) ( GLenum, const GLfloat * ) )qwglGetProcAddress( "glPointParameterfvEXT" );
ri.Con_Printf( PRINT_ALL, "...using GL_EXT_point_parameters\n" );
}
else
{
ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_point_parameters\n" );
}
}
else
{
ri.Con_Printf( PRINT_ALL, "...GL_EXT_point_parameters not found\n" );
}
if ( !qglColorTableEXT &&
strstr( gl_config.extensions_string, "GL_EXT_paletted_texture" ) &&
strstr( gl_config.extensions_string, "GL_EXT_shared_texture_palette" ) )
{
if ( gl_ext_palettedtexture->value )
{
ri.Con_Printf( PRINT_ALL, "...using GL_EXT_shared_texture_palette\n" );
qglColorTableEXT =
( void (APIENTRY *) ( GLenum, GLenum, GLsizei, GLenum, GLenum, const GLvoid * ) )qwglGetProcAddress(
"glColorTableEXT" );
}
else
{
ri.Con_Printf( PRINT_ALL, "...ignoring GL_EXT_shared_texture_palette\n" );
}
}
else
{
ri.Con_Printf( PRINT_ALL, "...GL_EXT_shared_texture_palette not found\n" );
}
if ( strstr( gl_config.extensions_string, "GL_ARB_multitexture" ) )
{
if ( gl_ext_multitexture->value )
{
ri.Con_Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
qglMTexCoord2fSGIS = (void *) qwglGetProcAddress( "glMultiTexCoord2fARB" );
qglActiveTextureARB = (void *) qwglGetProcAddress( "glActiveTextureARB" );
qglClientActiveTextureARB = (void *) qwglGetProcAddress( "glClientActiveTextureARB" );
QGL_TEXTURE0 = GL_TEXTURE0_ARB;
QGL_TEXTURE1 = GL_TEXTURE1_ARB;
}
else
{
ri.Con_Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
}
else
{
ri.Con_Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
if ( strstr( gl_config.extensions_string, "GL_SGIS_multitexture" ) )
{
if ( qglActiveTextureARB )
{
ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture deprecated in favor of ARB_multitexture\n" );
}
else if ( gl_ext_multitexture->value )
{
ri.Con_Printf( PRINT_ALL, "...using GL_SGIS_multitexture\n" );
qglMTexCoord2fSGIS = (void *) qwglGetProcAddress( "glMTexCoord2fSGIS" );
qglSelectTextureSGIS = (void *) qwglGetProcAddress( "glSelectTextureSGIS" );
QGL_TEXTURE0 = GL_TEXTURE0_SGIS;
QGL_TEXTURE1 = GL_TEXTURE1_SGIS;
}
else
{
ri.Con_Printf( PRINT_ALL, "...ignoring GL_SGIS_multitexture\n" );
}
}
else
{
ri.Con_Printf( PRINT_ALL, "...GL_SGIS_multitexture not found\n" );
}
2011-10-17 10:43:48 +00:00
gl_config.anisotropic = false;
if ( strstr(gl_config.extensions_string,"GL_EXT_texture_filter_anisotropic") )
{
ri.Con_Printf (PRINT_ALL,"...using GL_EXT_texture_filter_anisotropic\n" );
gl_config.anisotropic = true;
qglGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl_config.max_anisotropy);
ri.Cvar_SetValue("gl_anisotropic_avail", gl_config.max_anisotropy);
}
else
{
ri.Con_Printf (PRINT_ALL,"..GL_EXT_texture_filter_anisotropic not found\n" );
gl_config.anisotropic = false;
gl_config.max_anisotropy = 0.0;
ri.Cvar_SetValue("gl_anisotropic_avail", 0.0);
}
2010-10-25 13:21:52 +00:00
gl_config.mtexcombine = false;
if ( strstr( gl_config.extensions_string, "GL_ARB_texture_env_combine" ) )
{
if ( gl_ext_mtexcombine->value )
{
Com_Printf( "...using GL_ARB_texture_env_combine\n" );
gl_config.mtexcombine = true;
}
else
{
Com_Printf( "...ignoring GL_ARB_texture_env_combine\n" );
}
}
else
{
Com_Printf( "...GL_ARB_texture_env_combine not found\n" );
}
if ( !gl_config.mtexcombine )
{
if ( strstr( gl_config.extensions_string, "GL_EXT_texture_env_combine" ) )
{
if ( gl_ext_mtexcombine->value )
{
Com_Printf( "...using GL_EXT_texture_env_combine\n" );
gl_config.mtexcombine = true;
}
else
{
Com_Printf( "...ignoring GL_EXT_texture_env_combine\n" );
}
}
else
{
Com_Printf( "...GL_EXT_texture_env_combine not found\n" );
}
}
R_SetDefaultState();
R_InitImages();
Mod_Init();
R_InitParticleTexture();
Draw_InitLocal();
err = qglGetError();
if ( err != GL_NO_ERROR )
{
ri.Con_Printf( PRINT_ALL, "glGetError() = 0x%x\n", err );
}
return ( true );
}
void
R_Shutdown ( void )
{
ri.Cmd_RemoveCommand( "modellist" );
ri.Cmd_RemoveCommand( "screenshot" );
ri.Cmd_RemoveCommand( "imagelist" );
ri.Cmd_RemoveCommand( "gl_strings" );
Mod_FreeAll();
R_ShutdownImages();
/* shut down OS specific OpenGL stuff like contexts, etc. */
GLimp_Shutdown();
/* shutdown our QGL subsystem */
QGL_Shutdown();
}
extern void UpdateHardwareGamma ();
void
R_BeginFrame ( float camera_separation )
{
gl_state.camera_separation = camera_separation;
/* change modes if necessary */
if ( gl_mode->modified || vid_fullscreen->modified )
{
cvar_t *ref;
ref = ri.Cvar_Get( "vid_ref", "gl", 0 );
ref->modified = true;
}
if ( gl_log->modified )
{
GLimp_EnableLogging( gl_log->value );
gl_log->modified = false;
}
if ( gl_log->value )
{
GLimp_LogNewFrame();
}
if ( vid_gamma->modified )
{
vid_gamma->modified = false;
if ( gl_state.hwgamma )
{
UpdateHardwareGamma();
}
}
/* go into 2D mode */
qglViewport( 0, 0, vid.width, vid.height );
qglMatrixMode( GL_PROJECTION );
qglLoadIdentity();
qglOrtho( 0, vid.width, vid.height, 0, -99999, 99999 );
qglMatrixMode( GL_MODELVIEW );
qglLoadIdentity();
qglDisable( GL_DEPTH_TEST );
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
qglEnable( GL_ALPHA_TEST );
qglColor4f( 1, 1, 1, 1 );
/* draw buffer stuff */
if ( gl_drawbuffer->modified )
{
gl_drawbuffer->modified = false;
if ( ( gl_state.camera_separation == 0 ) || !gl_state.stereo_enabled )
{
if ( Q_stricmp( gl_drawbuffer->string, "GL_FRONT" ) == 0 )
{
qglDrawBuffer( GL_FRONT );
}
else
{
qglDrawBuffer( GL_BACK );
}
}
}
/* texturemode stuff */
if ( gl_texturemode->modified )
{
R_TextureMode( gl_texturemode->string );
gl_texturemode->modified = false;
}
if ( gl_texturealphamode->modified )
{
R_TextureAlphaMode( gl_texturealphamode->string );
gl_texturealphamode->modified = false;
}
if ( gl_texturesolidmode->modified )
{
R_TextureSolidMode( gl_texturesolidmode->string );
gl_texturesolidmode->modified = false;
}
/* swapinterval stuff */
R_UpdateSwapInterval();
/* clear screen if desired */
R_Clear();
}
void
R_SetPalette ( const unsigned char *palette )
{
int i;
byte *rp = (byte *) r_rawpalette;
if ( palette )
{
for ( i = 0; i < 256; i++ )
{
rp [ i * 4 + 0 ] = palette [ i * 3 + 0 ];
rp [ i * 4 + 1 ] = palette [ i * 3 + 1 ];
rp [ i * 4 + 2 ] = palette [ i * 3 + 2 ];
rp [ i * 4 + 3 ] = 0xff;
}
}
else
{
for ( i = 0; i < 256; i++ )
{
rp [ i * 4 + 0 ] = LittleLong( d_8to24table [ i ] ) & 0xff;
rp [ i * 4 + 1 ] = ( LittleLong( d_8to24table [ i ] ) >> 8 ) & 0xff;
rp [ i * 4 + 2 ] = ( LittleLong( d_8to24table [ i ] ) >> 16 ) & 0xff;
rp [ i * 4 + 3 ] = 0xff;
}
}
R_SetTexturePalette( r_rawpalette );
qglClearColor( 0, 0, 0, 0 );
qglClear( GL_COLOR_BUFFER_BIT );
qglClearColor( 1, 0, 0.5, 0.5 );
}
/* R_DrawBeam */
void
R_DrawBeam ( entity_t *e )
{
int i;
float r, g, b;
vec3_t perpvec;
vec3_t direction, normalized_direction;
vec3_t start_points [ NUM_BEAM_SEGS ], end_points [ NUM_BEAM_SEGS ];
vec3_t oldorigin, origin;
oldorigin [ 0 ] = e->oldorigin [ 0 ];
oldorigin [ 1 ] = e->oldorigin [ 1 ];
oldorigin [ 2 ] = e->oldorigin [ 2 ];
origin [ 0 ] = e->origin [ 0 ];
origin [ 1 ] = e->origin [ 1 ];
origin [ 2 ] = e->origin [ 2 ];
normalized_direction [ 0 ] = direction [ 0 ] = oldorigin [ 0 ] - origin [ 0 ];
normalized_direction [ 1 ] = direction [ 1 ] = oldorigin [ 1 ] - origin [ 1 ];
normalized_direction [ 2 ] = direction [ 2 ] = oldorigin [ 2 ] - origin [ 2 ];
if ( VectorNormalize( normalized_direction ) == 0 )
{
return;
}
PerpendicularVector( perpvec, normalized_direction );
VectorScale( perpvec, e->frame / 2, perpvec );
for ( i = 0; i < 6; i++ )
{
RotatePointAroundVector( start_points [ i ], normalized_direction, perpvec, ( 360.0 / NUM_BEAM_SEGS ) * i );
VectorAdd( start_points [ i ], origin, start_points [ i ] );
VectorAdd( start_points [ i ], direction, end_points [ i ] );
}
qglDisable( GL_TEXTURE_2D );
qglEnable( GL_BLEND );
qglDepthMask( GL_FALSE );
r = ( LittleLong( d_8to24table [ e->skinnum & 0xFF ] ) ) & 0xFF;
g = ( LittleLong( d_8to24table [ e->skinnum & 0xFF ] ) >> 8 ) & 0xFF;
b = ( LittleLong( d_8to24table [ e->skinnum & 0xFF ] ) >> 16 ) & 0xFF;
r *= 1 / 255.0F;
g *= 1 / 255.0F;
b *= 1 / 255.0F;
qglColor4f( r, g, b, e->alpha );
qglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < NUM_BEAM_SEGS; i++ )
{
qglVertex3fv( start_points [ i ] );
qglVertex3fv( end_points [ i ] );
qglVertex3fv( start_points [ ( i + 1 ) % NUM_BEAM_SEGS ] );
qglVertex3fv( end_points [ ( i + 1 ) % NUM_BEAM_SEGS ] );
}
qglEnd();
qglEnable( GL_TEXTURE_2D );
qglDisable( GL_BLEND );
qglDepthMask( GL_TRUE );
}
refexport_t
R_GetRefAPI ( refimport_t rimp )
{
refexport_t re;
ri = rimp;
re.api_version = API_VERSION;
re.BeginRegistration = R_BeginRegistration;
re.RegisterModel = R_RegisterModel;
re.RegisterSkin = R_RegisterSkin;
re.RegisterPic = Draw_FindPic;
re.SetSky = R_SetSky;
re.EndRegistration = R_EndRegistration;
re.RenderFrame = R_RenderFrame;
re.DrawGetPicSize = Draw_GetPicSize;
re.DrawPic = Draw_Pic;
re.DrawStretchPic = Draw_StretchPic;
re.DrawChar = Draw_Char;
re.DrawTileClear = Draw_TileClear;
re.DrawFill = Draw_Fill;
re.DrawFadeScreen = Draw_FadeScreen;
re.DrawStretchRaw = Draw_StretchRaw;
re.Init = R_Init;
re.Shutdown = R_Shutdown;
re.CinematicSetPalette = R_SetPalette;
re.BeginFrame = R_BeginFrame;
re.EndFrame = GLimp_EndFrame;
2010-10-19 12:43:11 +00:00
re.AppActivate = NULL;
Swap_Init();
return ( re );
}
/*
* this is only here so the functions in
* q_shared.c can link
*/
void
Sys_Error ( char *error, ... )
{
va_list argptr;
char text [ 1024 ];
va_start( argptr, error );
vsprintf( text, error, argptr );
va_end( argptr );
ri.Sys_Error( ERR_FATAL, "%s", text );
}
void
Com_Printf ( char *fmt, ... )
{
va_list argptr;
char text [ 1024 ];
va_start( argptr, fmt );
vsprintf( text, fmt, argptr );
va_end( argptr );
ri.Con_Printf( PRINT_ALL, "%s", text );
}
2009-03-05 12:42:43 +00:00