#include "quakedef.h"
-entity_render_t *currentrenderentity;
+// used for dlight push checking and other things
+int r_framecount;
-int r_framecount; // used for dlight push checking
+mplane_t frustum[4];
-mplane_t frustum[4];
+int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
-int c_brush_polys, c_alias_polys, c_light_polys, c_faces, c_nodes, c_leafs, c_models, c_bmodels, c_sprites, c_particles, c_dlights;
+// true during envmap command capture
+qboolean envmap;
-qboolean envmap; // true during envmap command capture
+float r_farclip;
-//
// view origin
-//
-vec3_t vup;
-vec3_t vpn;
-vec3_t vright;
-vec3_t r_origin;
+vec3_t r_origin;
+vec3_t vpn;
+vec3_t vright;
+vec3_t vup;
//
// screen size info
//
-refdef_t r_refdef;
+refdef_t r_refdef;
-mleaf_t *r_viewleaf, *r_oldviewleaf;
+mleaf_t *r_viewleaf, *r_oldviewleaf;
-unsigned short d_lightstylevalue[256]; // 8.8 fraction of base light value
+// 8.8 fraction of base light value
+unsigned short d_lightstylevalue[256];
-cvar_t r_drawentities = {0, "r_drawentities","1"};
-cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
-cvar_t r_speeds = {0, "r_speeds","0"};
-cvar_t r_fullbright = {0, "r_fullbright","0"};
-cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
-cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
-cvar_t r_waterripple = {CVAR_SAVE, "r_waterripple","0"};
-cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
+cvar_t r_drawentities = {0, "r_drawentities","1"};
+cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1"};
+cvar_t r_speeds = {0, "r_speeds","0"};
+cvar_t r_fullbright = {0, "r_fullbright","0"};
+cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1"};
+cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1"};
+cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1"};
-cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
-cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
-cvar_t gl_fogred = {0, "gl_fogred","0.3"};
-cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
-cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
-cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
-cvar_t gl_fogend = {0, "gl_fogend","0"};
+cvar_t gl_fogenable = {0, "gl_fogenable", "0"};
+cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25"};
+cvar_t gl_fogred = {0, "gl_fogred","0.3"};
+cvar_t gl_foggreen = {0, "gl_foggreen","0.3"};
+cvar_t gl_fogblue = {0, "gl_fogblue","0.3"};
+cvar_t gl_fogstart = {0, "gl_fogstart", "0"};
+cvar_t gl_fogend = {0, "gl_fogend","0"};
-cvar_t r_ser = {CVAR_SAVE, "r_ser", "0"};
+cvar_t r_textureunits = {0, "r_textureunits", "32"};
-cvar_t r_multitexture = {0, "r_multitexture", "1"};
+void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
+{
+ int i;
+ for (i = 0;i < verts;i++)
+ {
+ out[0] = in[0] * r;
+ out[1] = in[1] * g;
+ out[2] = in[2] * b;
+ out[3] = in[3];
+ in += 4;
+ out += 4;
+ }
+}
+
+void R_FillColors(float *out, int verts, float r, float g, float b, float a)
+{
+ int i;
+ for (i = 0;i < verts;i++)
+ {
+ out[0] = r;
+ out[1] = g;
+ out[2] = b;
+ out[3] = a;
+ out += 4;
+ }
+}
/*
====================
qboolean intimerefresh = 0;
static void R_TimeRefresh_f (void)
{
- int i;
- float start, stop, time;
+ int i;
+ float start, stop, time;
intimerefresh = 1;
start = Sys_DoubleTime ();
Cvar_RegisterVariable (&r_fullbrights);
Cvar_RegisterVariable (&r_wateralpha);
Cvar_RegisterVariable (&r_dynamic);
- Cvar_RegisterVariable (&r_waterripple);
Cvar_RegisterVariable (&r_fullbright);
- Cvar_RegisterVariable (&r_ser);
- Cvar_RegisterVariable (&r_multitexture);
+ Cvar_RegisterVariable (&r_textureunits);
if (gamemode == GAME_NEHAHRA)
Cvar_SetValue("r_fullbrights", 0);
R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap);
}
+vec3_t r_farclip_origin;
+vec3_t r_farclip_direction;
+vec_t r_farclip_directiondist;
+vec_t r_farclip_meshfarclip;
+int r_farclip_directionbit0;
+int r_farclip_directionbit1;
+int r_farclip_directionbit2;
+
+// start a farclip measuring session
+void R_FarClip_Start(vec3_t origin, vec3_t direction, vec_t startfarclip)
+{
+ VectorCopy(origin, r_farclip_origin);
+ VectorCopy(direction, r_farclip_direction);
+ r_farclip_directiondist = DotProduct(r_farclip_origin, r_farclip_direction);
+ r_farclip_directionbit0 = r_farclip_direction[0] < 0;
+ r_farclip_directionbit1 = r_farclip_direction[1] < 0;
+ r_farclip_directionbit2 = r_farclip_direction[2] < 0;
+ r_farclip_meshfarclip = r_farclip_directiondist + startfarclip;
+}
+
+// enlarge farclip to accomodate box
+void R_FarClip_Box(vec3_t mins, vec3_t maxs)
+{
+ float d;
+ d = (r_farclip_directionbit0 ? mins[0] : maxs[0]) * r_farclip_direction[0]
+ + (r_farclip_directionbit1 ? mins[1] : maxs[1]) * r_farclip_direction[1]
+ + (r_farclip_directionbit2 ? mins[2] : maxs[2]) * r_farclip_direction[2];
+ if (r_farclip_meshfarclip < d)
+ r_farclip_meshfarclip = d;
+}
+
+// return farclip value
+float R_FarClip_Finish(void)
+{
+ return r_farclip_meshfarclip - r_farclip_directiondist;
+}
+
/*
===============
R_NewMap
void CL_ParseEntityLump(char *entitystring);
void R_NewMap (void)
{
- int i;
+ int i;
- for (i=0 ; i<256 ; i++)
+ for (i = 0;i < 256;i++)
d_lightstylevalue[i] = 264; // normal light value
r_viewleaf = NULL;
if (cl.worldmodel->entities)
CL_ParseEntityLump(cl.worldmodel->entities);
R_Modules_NewMap();
+
+ r_farclip = 64.0f;
}
extern void R_Textures_Init(void);
extern void R_Light_Init(void);
extern void R_Particles_Init(void);
extern void R_Explosion_Init(void);
-extern void R_Clip_Init(void);
extern void ui_init(void);
extern void gl_backend_init(void);
R_Textures_Init();
Mod_RenderInit();
gl_backend_init();
- R_Clip_Init();
+ R_MeshQueue_Init();
GL_Draw_Init();
GL_Main_Init();
GL_Models_Init();
extern char *ENGINE_EXTENSIONS;
void GL_Init (void)
{
- gl_vendor = glGetString (GL_VENDOR);
- Con_Printf ("GL_VENDOR: %s\n", gl_vendor);
- gl_renderer = glGetString (GL_RENDERER);
- Con_Printf ("GL_RENDERER: %s\n", gl_renderer);
-
- gl_version = glGetString (GL_VERSION);
- Con_Printf ("GL_VERSION: %s\n", gl_version);
- gl_extensions = glGetString (GL_EXTENSIONS);
- Con_Printf ("GL_EXTENSIONS: %s\n", gl_extensions);
-
VID_CheckExtensions();
// LordHavoc: report supported extensions
//==================================================================================
-void R_Entity_Callback(void *data, void *junk)
-{
- ((entity_render_t *)data)->visframe = r_framecount;
-}
-
static void R_MarkEntities (void)
{
- int i;
- vec3_t v;
+ int i;
+ vec3_t v;
+ entity_render_t *ent;
+
+ ent = &cl_entities[0].render;
+ Matrix4x4_CreateIdentity(&ent->matrix);
+ Matrix4x4_CreateIdentity(&ent->inversematrix);
+
+ R_FarClip_Box(cl.worldmodel->normalmins, cl.worldmodel->normalmaxs);
if (!r_drawentities.integer)
return;
for (i = 0;i < r_refdef.numentities;i++)
{
- currentrenderentity = r_refdef.entities[i];
- Mod_CheckLoaded(currentrenderentity->model);
+ ent = r_refdef.entities[i];
+ Mod_CheckLoaded(ent->model);
// move view-relative models to where they should be
- if (currentrenderentity->flags & RENDER_VIEWMODEL)
+ if (ent->flags & RENDER_VIEWMODEL)
{
// remove flag so it will not be repeated incase RelinkEntities is not called again for a while
- currentrenderentity->flags -= RENDER_VIEWMODEL;
+ ent->flags -= RENDER_VIEWMODEL;
// transform origin
- VectorCopy(currentrenderentity->origin, v);
- currentrenderentity->origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
- currentrenderentity->origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
- currentrenderentity->origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
+ VectorCopy(ent->origin, v);
+ ent->origin[0] = v[0] * vpn[0] + v[1] * vright[0] + v[2] * vup[0] + r_origin[0];
+ ent->origin[1] = v[0] * vpn[1] + v[1] * vright[1] + v[2] * vup[1] + r_origin[1];
+ ent->origin[2] = v[0] * vpn[2] + v[1] * vright[2] + v[2] * vup[2] + r_origin[2];
// adjust angles
- VectorAdd(currentrenderentity->angles, r_refdef.viewangles, currentrenderentity->angles);
+ VectorAdd(ent->angles, r_refdef.viewangles, ent->angles);
}
- if (currentrenderentity->angles[0] || currentrenderentity->angles[2])
+ if (ent->angles[0] || ent->angles[2])
{
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmins, currentrenderentity->mins);
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->rotatedmaxs, currentrenderentity->maxs);
+ VectorMA(ent->origin, ent->scale, ent->model->rotatedmins, ent->mins);
+ VectorMA(ent->origin, ent->scale, ent->model->rotatedmaxs, ent->maxs);
}
- else if (currentrenderentity->angles[1])
+ else if (ent->angles[1])
{
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmins, currentrenderentity->mins);
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->yawmaxs, currentrenderentity->maxs);
+ VectorMA(ent->origin, ent->scale, ent->model->yawmins, ent->mins);
+ VectorMA(ent->origin, ent->scale, ent->model->yawmaxs, ent->maxs);
}
else
{
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmins, currentrenderentity->mins);
- VectorMA(currentrenderentity->origin, currentrenderentity->scale, currentrenderentity->model->normalmaxs, currentrenderentity->maxs);
+ VectorMA(ent->origin, ent->scale, ent->model->normalmins, ent->mins);
+ VectorMA(ent->origin, ent->scale, ent->model->normalmaxs, ent->maxs);
}
- if (R_VisibleCullBox(currentrenderentity->mins, currentrenderentity->maxs))
+ if (R_VisibleCullBox(ent->mins, ent->maxs))
continue;
- R_LerpAnimation(currentrenderentity);
- if (r_ser.integer)
- currentrenderentity->model->SERAddEntity();
- else
- currentrenderentity->visframe = r_framecount;
+ VectorCopy(ent->angles, v);
+ if (ent->model->type != mod_brush)
+ v[0] = -v[0];
+ Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], v[0], v[1], v[2], ent->scale);
+ Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
+ R_LerpAnimation(ent);
+ ent->visframe = r_framecount;
+
+ R_FarClip_Box(ent->mins, ent->maxs);
+
+ R_UpdateEntLights(ent);
}
}
// only used if skyrendermasked, and normally returns false
int R_DrawBModelSky (void)
{
- int i, sky = false;
+ int i, sky;
+ entity_render_t *ent;
if (!r_drawentities.integer)
return false;
+ sky = false;
for (i = 0;i < r_refdef.numentities;i++)
{
- currentrenderentity = r_refdef.entities[i];
- if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->DrawSky)
+ ent = r_refdef.entities[i];
+ if (ent->visframe == r_framecount && ent->model->DrawSky)
{
- currentrenderentity->model->DrawSky();
+ ent->model->DrawSky(ent);
sky = true;
}
}
void R_DrawModels (void)
{
- int i;
+ int i;
+ entity_render_t *ent;
if (!r_drawentities.integer)
return;
for (i = 0;i < r_refdef.numentities;i++)
{
- currentrenderentity = r_refdef.entities[i];
- if (currentrenderentity->visframe == r_framecount && currentrenderentity->model->Draw)
- currentrenderentity->model->Draw();
+ ent = r_refdef.entities[i];
+ if (ent->visframe == r_framecount && ent->model->Draw)
+ ent->model->Draw(ent);
}
}
*/
void R_DrawViewModel (void)
{
+ entity_render_t *ent;
+
// FIXME: move these checks to client
if (!r_drawviewmodel.integer || chase_active.integer || envmap || !r_drawentities.integer || cl.items & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !cl.viewent.render.model)
return;
- currentrenderentity = &cl.viewent.render;
- Mod_CheckLoaded(currentrenderentity->model);
-
- R_LerpAnimation(currentrenderentity);
-
- currentrenderentity->model->Draw();
+ ent = &cl.viewent.render;
+ Mod_CheckLoaded(ent->model);
+ R_LerpAnimation(ent);
+ Matrix4x4_CreateFromQuakeEntity(&ent->matrix, ent->origin[0], ent->origin[1], ent->origin[2], -ent->angles[0], ent->angles[1], ent->angles[2], ent->scale);
+ Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
+ R_UpdateEntLights(ent);
+ ent->model->Draw(ent);
}
static void R_SetFrustum (void)
{
- int i;
+ int i;
// LordHavoc: note to all quake engine coders, the special case for 90
// degrees assumed a square view (wrong), so I removed it, Quake2 has it
// rotate VPN down by FOV_X/2 degrees
RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
-
- for (i=0 ; i<4 ; i++)
+ for (i = 0;i < 4;i++)
{
frustum[i].type = PLANE_ANYZ;
frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
if (r_ambient.value != 0)
Cvar_Set ("r_ambient", "0");
}
- if (r_multitexture.integer && gl_textureunits < 2)
- Cvar_SetValue("r_multitexture", 0);
r_framecount++;
}
-static int blendviewpolyindex[3] = {0, 1, 2};
-
static void R_BlendView(void)
{
- rmeshinfo_t m;
- float tvxyz[3][4], r;
+ rmeshbufferinfo_t m;
+ float r;
if (r_refdef.viewblend[3] < 0.01f)
return;
memset(&m, 0, sizeof(m));
- m.transparent = false;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
m.depthdisable = true; // magic
m.numtriangles = 1;
m.numverts = 3;
- m.index = blendviewpolyindex;
- m.vertex = &tvxyz[0][0];
- m.vertexstep = sizeof(float[4]);
- m.cr = r_refdef.viewblend[0];
- m.cg = r_refdef.viewblend[1];
- m.cb = r_refdef.viewblend[2];
- m.ca = r_refdef.viewblend[3];
- r = 64000;
- tvxyz[0][0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
- tvxyz[0][1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
- tvxyz[0][2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
- r *= 3;
- tvxyz[1][0] = tvxyz[0][0] + vup[0] * r;
- tvxyz[1][1] = tvxyz[0][1] + vup[1] * r;
- tvxyz[1][2] = tvxyz[0][2] + vup[2] * r;
- tvxyz[2][0] = tvxyz[0][0] + vright[0] * r;
- tvxyz[2][1] = tvxyz[0][1] + vright[1] * r;
- tvxyz[2][2] = tvxyz[0][2] + vright[2] * r;
- R_Mesh_Draw(&m);
+ Matrix4x4_CreateIdentity(&m.matrix);
+ if (R_Mesh_Draw_GetBuffer(&m, false))
+ {
+ m.index[0] = 0;
+ m.index[1] = 1;
+ m.index[2] = 2;
+ m.color[0] = m.color[4] = m.color[8] = r_refdef.viewblend[0];
+ m.color[1] = m.color[5] = m.color[9] = r_refdef.viewblend[1];
+ m.color[2] = m.color[6] = m.color[10] = r_refdef.viewblend[2];
+ m.color[3] = m.color[7] = m.color[11] = r_refdef.viewblend[3];
+ r = 64000;
+ m.vertex[0] = r_origin[0] + vpn[0] * 1.5 - vright[0] * r - vup[0] * r;
+ m.vertex[1] = r_origin[1] + vpn[1] * 1.5 - vright[1] * r - vup[1] * r;
+ m.vertex[2] = r_origin[2] + vpn[2] * 1.5 - vright[2] * r - vup[2] * r;
+ r *= 3;
+ m.vertex[4] = m.vertex[0] + vup[0] * r;
+ m.vertex[5] = m.vertex[1] + vup[1] * r;
+ m.vertex[6] = m.vertex[2] + vup[2] * r;
+ m.vertex[8] = m.vertex[0] + vright[0] * r;
+ m.vertex[9] = m.vertex[1] + vright[1] * r;
+ m.vertex[10] = m.vertex[2] + vright[2] * r;
+ R_Mesh_Render();
+ }
}
/*
*/
void R_RenderView (void)
{
+ entity_render_t *world = &cl_entities[0].render;
if (!cl.worldmodel)
return; //Host_Error ("R_RenderView: NULL worldmodel");
R_SetFrustum();
R_SetupFog();
R_SkyStartFrame();
- if (r_ser.integer)
- R_Clip_StartFrame();
R_BuildLightList();
- R_Mesh_Start();
+ R_FarClip_Start(r_origin, vpn, 768.0f);
R_TimeReport("setup");
- R_DrawWorld();
+ R_DrawWorld(world);
R_TimeReport("worldnode");
R_MarkEntities();
R_TimeReport("markentity");
- if (r_ser.integer)
- {
- R_Clip_EndFrame();
- R_TimeReport("hiddensurf");
- }
-
- R_MarkWorldLights();
+ R_SurfMarkLights(world);
R_TimeReport("marklights");
+ r_farclip = R_FarClip_Finish() + 256.0f;
+
+ R_Mesh_Start(r_farclip);
+
+ R_MeshQueue_BeginScene();
+
+
if (skyrendermasked)
{
if (R_DrawBModelSky())
R_TimeReport("viewmodel");
}
- R_SetupForWorldRendering();
- R_PrepareSurfaces();
+ R_PrepareSurfaces(world);
R_TimeReport("surfprep");
- R_DrawSurfaces(SHADERSTAGE_SKY);
- R_DrawSurfaces(SHADERSTAGE_NORMAL);
+ R_DrawSurfaces(world, SHADERSTAGE_SKY);
+ R_DrawSurfaces(world, SHADERSTAGE_NORMAL);
R_TimeReport("surfdraw");
if (r_drawportals.integer)
{
- R_DrawPortals();
+ R_DrawPortals(world);
R_TimeReport("portals");
}
R_DrawExplosions();
R_TimeReport("explosions");
- // draw transparent meshs
- R_Mesh_AddTransparent();
+ R_MeshQueue_RenderTransparent();
R_TimeReport("addtrans");
R_DrawCoronas();
R_TimeReport("coronas");
+ R_DrawCrosshair();
+ R_TimeReport("crosshair");
+
R_BlendView();
R_TimeReport("blendview");
- R_DrawCrosshair();
- R_TimeReport("crosshair");
+ R_MeshQueue_Render();
+
+ R_MeshQueue_EndScene();
- // render any queued meshs
R_Mesh_Finish();
R_TimeReport("meshfinish");
}