📄 gl_rmain.c
字号:
/*
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.
*/
// r_main.c
#include "gl_local.h"
void R_Clear (void);
viddef_t vid;
refimport_t ri;
int GL_TEXTURE0, GL_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 GL_Strings_f( 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;
cvar_t *r_norefresh;
cvar_t *r_drawentities;
cvar_t *r_drawworld;
cvar_t *r_speeds;
cvar_t *r_fullbright;
cvar_t *r_novis;
cvar_t *r_nocull;
cvar_t *r_lerpmodels;
cvar_t *r_lefthand;
cvar_t *r_lightlevel; // FIXME: This is a HACK to get the client's light level
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;
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_mode;
cvar_t *gl_dynamic;
cvar_t *gl_monolightmap;
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;
cvar_t *gl_lockpvs;
cvar_t *gl_3dlabs_broken;
cvar_t *vid_fullscreen;
cvar_t *vid_gamma;
cvar_t *vid_ref;
/*
=================
R_CullBox
Returns true if the box is completely outside the frustom
=================
*/
qboolean R_CullBox (vec3_t mins, vec3_t maxs)
{
int i;
if (r_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);
}
/*
=============================================================
SPRITE MODELS
=============================================================
*/
/*
=================
R_DrawSpriteModel
=================
*/
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;
#if 0
if (e->frame < 0 || e->frame >= psprite->numframes)
{
ri.Con_Printf (PRINT_ALL, "no such sprite frame %i\n", e->frame);
e->frame = 0;
}
#endif
e->frame %= psprite->numframes;
frame = &psprite->frames[e->frame];
#if 0
if (psprite->type == SPR_ORIENTED)
{ // bullet marks on walls
vec3_t v_forward, v_right, v_up;
AngleVectors (currententity->angles, v_forward, v_right, v_up);
up = v_up;
right = v_right;
}
else
#endif
{ // 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 );
GL_Bind(currentmodel->skins[e->frame]->texnum);
GL_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);
GL_TexEnv( GL_REPLACE );
if ( alpha != 1.0F )
qglDisable( GL_BLEND );
qglColor4f( 1, 1, 1, 1 );
}
//==================================================================================
/*
=============
R_DrawNullModel
=============
*/
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);
}
/*
=============
R_DrawEntitiesOnList
=============
*/
void R_DrawEntitiesOnList (void)
{
int i;
if (!r_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
}
/*
** GL_DrawParticles
**
*/
void GL_DrawParticles( 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];
GL_Bind(r_particletexture->texnum);
qglDepthMask( GL_FALSE ); // no z buffering
qglEnable( GL_BLEND );
GL_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
GL_TexEnv( GL_REPLACE );
}
/*
===============
R_DrawParticles
===============
*/
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( 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];
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
{
GL_DrawParticles( r_newrefdef.num_particles, r_newrefdef.particles, d_8to24table );
}
}
/*
============
R_PolyBlend
============
*/
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 ();
// FIXME: get rid of these
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 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;
#if 0
/*
** this code is wrong, since it presume a 90 degree FOV both in the
** horizontal and vertical plane
*/
// front side is visible
VectorAdd (vpn, vright, frustum[0].normal);
VectorSubtract (vpn, vright, frustum[1].normal);
VectorAdd (vpn, vup, frustum[2].normal);
VectorSubtract (vpn, vup, frustum[3].normal);
// we theoretically don't need to normalize these vectors, but I do it
// anyway so that debugging is a little easier
VectorNormalize( frustum[0].normal );
VectorNormalize( frustum[1].normal );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -