cl.num_temp_entities = 0;
}
-entity_t *CL_NewTempEntity(void)
+entity_t *CL_NewTempEntity(renderscene_t* scene)
{
entity_t *ent;
- if (r_refdef.numentities >= r_refdef.maxentities)
+ if (scene->refdef.numentities >= r_refdef.maxentities)
return NULL;
if (cl.num_temp_entities >= cl.max_temp_entities)
return NULL;
ent = &cl.temp_entities[cl.num_temp_entities++];
memset (ent, 0, sizeof(*ent));
- r_refdef.entities[r_refdef.numentities++] = &ent->render;
+ scene->refdef.entities[scene->refdef.numentities++] = &ent->render;
ent->render.alpha = 1;
VectorSet(ent->render.colormod, 1, 1, 1);
}
// end of code taken from QuakeWorld
- flag = CL_NewTempEntity();
+ flag = CL_NewTempEntity(&client_scene);
if (!flag)
return;
// if we're drawing effects, get a new temp entity
// (NewTempEntity adds it to the render entities list for us)
- if (r_draweffects.integer && (ent = CL_NewTempEntity()))
+ if (r_draweffects.integer && (ent = CL_NewTempEntity(&client_scene)))
{
// interpolation stuff
ent->render.frame1 = intframe;
d = VectorNormalizeLength(dist);
while (d > 0)
{
- ent = CL_NewTempEntity ();
+ ent = CL_NewTempEntity (&client_scene);
if (!ent)
return;
//VectorCopy (org, ent->render.origin);
// if we're drawing effects, get a new temp entity
// (NewTempEntity adds it to the render entities list for us)
- if (!(ent = CL_NewTempEntity()))
+ if (!(ent = CL_NewTempEntity(&client_scene)))
continue;
// normal stuff
CL_Init
=================
*/
+void CL_InitScene (renderscene_t* scene, mempool_t* pool)
+{
+ memset(&scene->refdef, 0, sizeof(scene->refdef));
+ // max entities sent to renderer per frame
+ scene->refdef.maxentities = MAX_EDICTS + 256 + 512;
+ scene->refdef.entities = (entity_render_t **)Mem_Alloc(pool, sizeof(entity_render_t *) * scene->refdef.maxentities);
+}
+
void CL_Init (void)
{
cls.levelmempool = Mem_AllocPool("client (per-level memory)", 0, NULL);
cls.permanentmempool = Mem_AllocPool("client (long term memory)", 0, NULL);
- memset(&r_refdef, 0, sizeof(r_refdef));
- // max entities sent to renderer per frame
- r_refdef.maxentities = MAX_EDICTS + 256 + 512;
- r_refdef.entities = (entity_render_t **)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t *) * r_refdef.maxentities);
+ CL_InitScene (&client_scene, cls.permanentmempool);
CL_InitInput ();
r_refdef.envmap = true;
- R_UpdateVariables();
+ R_UpdateVariables (&client_scene);
r_view.x = 0;
r_view.y = 0;
Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, r_view.origin[0], r_view.origin[1], r_view.origin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
r_view.clear = true;
R_Mesh_Start();
- R_RenderView();
+ R_RenderView(&client_scene);
R_Mesh_Finish();
SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_view.y + r_view.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
}
R_TimeReport_BeginFrame();
- R_UpdateVariables();
+ R_UpdateVariables (&client_scene);
// Quake uses clockwise winding, so these are swapped
r_view.cullface_front = GL_BACK;
r_view.frustum_y *= r_refdef.frustumscale_y;
if(!CL_VM_UpdateView())
- R_RenderView();
+ R_RenderView(&client_scene);
if (scr_zoomwindow.integer)
{
r_view.frustum_y *= r_refdef.frustumscale_y;
if(!CL_VM_UpdateView())
- R_RenderView();
+ R_RenderView(&client_scene);
}
}
void CL_ClientMovement_Replay(void);
void CL_ClearTempEntities (void);
-entity_t *CL_NewTempEntity (void);
+struct renderscene_s;
+entity_t *CL_NewTempEntity (struct renderscene_s* scene);
void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate);
}
r_viewcache_t;
-extern r_refdef_t r_refdef;
-extern r_view_t r_view;
-extern r_viewcache_t r_viewcache;
+typedef struct renderscene_s
+{
+ //
+ // screen size info
+ //
+ r_refdef_t refdef;
+ r_view_t view;
+ r_viewcache_t viewcache;
+} renderscene_t;
+
+void CL_InitScene (renderscene_t* scene, mempool_t* pool);
+
+extern renderscene_t client_scene;
+/* Convenience */
+#define r_refdef (client_scene.refdef)
+#define r_view (client_scene.view)
+#define r_viewcache (client_scene.viewcache)
#endif
#include "cl_collision.h"
#include "r_shadow.h"
+/* Per-VM scenes */
+renderscene_t* renderscenes[PRVM_MAXPROGS];
+#define RENDERSCENE (*renderscenes[prognum])
+
//============================================================================
// Client
//[515]: unsolved PROBLEMS
}
// #2 void(entity e, vector o) setorigin
-static void VM_CL_setorigin (void)
+void VM_CL_setorigin (void)
{
prvm_edict_t *e;
float *org;
}
// #3 void(entity e, string m) setmodel
-static void VM_CL_setmodel (void)
+void VM_CL_setmodel (void)
{
prvm_edict_t *e;
const char *m;
// #20 void(string s) precache_model
-static void VM_CL_precache_model (void)
+void VM_CL_precache_model (void)
{
const char *name;
int i;
//============================================================================
//[515]: SCENE MANAGER builtins
-extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
+extern qboolean CSQC_AddRenderEdict (renderscene_t* scene, prvm_edict_t *ed);//csprogs.c
static void CSQC_R_RecalcView (void)
{
extern matrix4x4_t viewmodelmatrix;
- Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
+ const int prognum = PRVM_GetProgNr();
+ Matrix4x4_CreateFromQuakeEntity(&RENDERSCENE.view.matrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], 1);
Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, cl.csqc_origin[0], cl.csqc_origin[1], cl.csqc_origin[2], cl.csqc_angles[0], cl.csqc_angles[1], cl.csqc_angles[2], cl_viewmodel_scale.value);
}
void CL_RelinkLightFlashes(void);
//#300 void() clearscene (EXT_CSQC)
-static void VM_CL_R_ClearScene (void)
+void VM_CL_R_ClearScene (void)
{
+ const int prognum = PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
// clear renderable entity and light lists
- r_refdef.numentities = 0;
- r_refdef.numlights = 0;
+ RENDERSCENE.refdef.numentities = 0;
+ RENDERSCENE.refdef.numlights = 0;
// FIXME: restore these to the values from VM_CL_UpdateView
- r_view.x = 0;
- r_view.y = 0;
- r_view.z = 0;
- r_view.width = vid.width;
- r_view.height = vid.height;
- r_view.depth = 1;
+ RENDERSCENE.view.x = 0;
+ RENDERSCENE.view.y = 0;
+ RENDERSCENE.view.z = 0;
+ RENDERSCENE.view.width = vid.width;
+ RENDERSCENE.view.height = vid.height;
+ RENDERSCENE.view.depth = 1;
// FIXME: restore frustum_x/frustum_y
- r_view.useperspective = true;
- r_view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
- r_view.frustum_x = r_view.frustum_y * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
- r_view.frustum_x *= r_refdef.frustumscale_x;
- r_view.frustum_y *= r_refdef.frustumscale_y;
- r_view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_view.width / (float)r_view.height / vid_pixelheight.value;
- r_view.ortho_y = scr_fov.value * (3.0 / 4.0);
+ RENDERSCENE.view.useperspective = true;
+ RENDERSCENE.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0) * cl.viewzoom;
+ RENDERSCENE.view.frustum_x = RENDERSCENE.view.frustum_y * (float)RENDERSCENE.view.width / (float)RENDERSCENE.view.height / vid_pixelheight.value;
+ RENDERSCENE.view.frustum_x *= RENDERSCENE.refdef.frustumscale_x;
+ RENDERSCENE.view.frustum_y *= RENDERSCENE.refdef.frustumscale_y;
+ RENDERSCENE.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)RENDERSCENE.view.width / (float)RENDERSCENE.view.height / vid_pixelheight.value;
+ RENDERSCENE.view.ortho_y = scr_fov.value * (3.0 / 4.0);
// FIXME: restore cl.csqc_origin
// FIXME: restore cl.csqc_angles
cl.csqc_vidvars.drawworld = true;
//#301 void(float mask) addentities (EXT_CSQC)
extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
-static void VM_CL_R_AddEntities (void)
+void VM_CL_R_AddEntities (void)
{
int i, drawmask;
prvm_edict_t *ed;
+ const int prognum = PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntities);
drawmask = (int)PRVM_G_FLOAT(OFS_PARM0);
CSQC_RelinkAllEntities(drawmask);
continue;
if(!((int)ed->fields.client->drawmask & drawmask))
continue;
- CSQC_AddRenderEdict(ed);
+ CSQC_AddRenderEdict(&RENDERSCENE, ed);
}
}
//#302 void(entity ent) addentity (EXT_CSQC)
-static void VM_CL_R_AddEntity (void)
+void VM_CL_R_AddEntity (void)
{
+ const int prognum = PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
- CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
+ CSQC_AddRenderEdict(&RENDERSCENE, PRVM_G_EDICT(OFS_PARM0));
}
//#303 float(float property, ...) setproperty (EXT_CSQC)
-static void VM_CL_R_SetView (void)
+void VM_CL_R_SetView (void)
{
int c;
float *f;
float k;
+ const int prognum = PRVM_GetProgNr();
VM_SAFEPARMCOUNTRANGE(2, 3, VM_CL_R_SetView);
switch(c)
{
case VF_MIN:
- r_view.x = (int)(f[0] * vid.width / vid_conwidth.value);
- r_view.y = (int)(f[1] * vid.height / vid_conheight.value);
+ RENDERSCENE.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.y = (int)(f[1] * vid.height / vid_conheight.value);
break;
case VF_MIN_X:
- r_view.x = (int)(k * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.x = (int)(k * vid.width / vid_conwidth.value);
break;
case VF_MIN_Y:
- r_view.y = (int)(k * vid.height / vid_conheight.value);
+ RENDERSCENE.view.y = (int)(k * vid.height / vid_conheight.value);
break;
case VF_SIZE:
- r_view.width = (int)(f[0] * vid.width / vid_conwidth.value);
- r_view.height = (int)(f[1] * vid.height / vid_conheight.value);
+ RENDERSCENE.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.height = (int)(f[1] * vid.height / vid_conheight.value);
break;
case VF_SIZE_Y:
- r_view.width = (int)(k * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.width = (int)(k * vid.width / vid_conwidth.value);
break;
case VF_SIZE_X:
- r_view.height = (int)(k * vid.height / vid_conheight.value);
+ RENDERSCENE.view.height = (int)(k * vid.height / vid_conheight.value);
break;
case VF_VIEWPORT:
- r_view.x = (int)(f[0] * vid.width / vid_conwidth.value);
- r_view.y = (int)(f[1] * vid.height / vid_conheight.value);
+ RENDERSCENE.view.x = (int)(f[0] * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.y = (int)(f[1] * vid.height / vid_conheight.value);
f = PRVM_G_VECTOR(OFS_PARM2);
- r_view.width = (int)(f[0] * vid.width / vid_conwidth.value);
- r_view.height = (int)(f[1] * vid.height / vid_conheight.value);
+ RENDERSCENE.view.width = (int)(f[0] * vid.width / vid_conwidth.value);
+ RENDERSCENE.view.height = (int)(f[1] * vid.height / vid_conheight.value);
break;
case VF_FOV:
- r_view.frustum_x = tan(f[0] * M_PI / 360.0);r_view.ortho_x = f[0];
- r_view.frustum_y = tan(f[1] * M_PI / 360.0);r_view.ortho_y = f[1];
+ RENDERSCENE.view.frustum_x = tan(f[0] * M_PI / 360.0);RENDERSCENE.view.ortho_x = f[0];
+ RENDERSCENE.view.frustum_y = tan(f[1] * M_PI / 360.0);RENDERSCENE.view.ortho_y = f[1];
break;
case VF_FOVX:
- r_view.frustum_x = tan(k * M_PI / 360.0);r_view.ortho_x = k;
+ RENDERSCENE.view.frustum_x = tan(k * M_PI / 360.0);RENDERSCENE.view.ortho_x = k;
break;
case VF_FOVY:
- r_view.frustum_y = tan(k * M_PI / 360.0);r_view.ortho_y = k;
+ RENDERSCENE.view.frustum_y = tan(k * M_PI / 360.0);RENDERSCENE.view.ortho_y = k;
break;
case VF_ORIGIN:
VectorCopy(f, cl.csqc_origin);
cl.viewangles[2] = k;
break;
case VF_PERSPECTIVE:
- r_view.useperspective = k != 0;
+ RENDERSCENE.view.useperspective = k != 0;
break;
default:
PRVM_G_FLOAT(OFS_RETURN) = 0;
}
//#304 void() renderscene (EXT_CSQC)
-static void VM_CL_R_RenderScene (void)
+void VM_CL_R_RenderScene (void)
{
+ const int prognum = PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
- // we need to update any RENDER_VIEWMODEL entities at this point because
+ // we need to update any RENDERENDERSCENE.viewMODEL entities at this point because
// csqc supplies its own view matrix
CL_UpdateViewEntities();
// now draw stuff!
- R_RenderView();
+ R_RenderView(&RENDERSCENE);
}
//#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-static void VM_CL_R_AddDynamicLight (void)
+void VM_CL_R_AddDynamicLight (void)
{
float *pos, *col;
matrix4x4_t matrix;
+ const int prognum = PRVM_GetProgNr();
+
VM_SAFEPARMCOUNTRANGE(3, 3, VM_CL_R_AddDynamicLight);
// if we've run out of dlights, just return
- if (r_refdef.numlights >= MAX_DLIGHTS)
+ if (RENDERSCENE.refdef.numlights >= MAX_DLIGHTS)
return;
pos = PRVM_G_VECTOR(OFS_PARM0);
col = PRVM_G_VECTOR(OFS_PARM2);
Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1));
- R_RTLight_Update(&r_refdef.lights[r_refdef.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+ R_RTLight_Update(&RENDERSCENE.refdef.lights[RENDERSCENE.refdef.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
}
//============================================================================
{
float *f;
vec3_t temp;
+ const int prognum = PRVM_GetProgNr();
VM_SAFEPARMCOUNT(1, VM_CL_unproject);
f = PRVM_G_VECTOR(OFS_PARM0);
- VectorSet(temp, f[2], f[0] * f[2] * -r_view.frustum_x * 2.0 / r_view.width, f[1] * f[2] * -r_view.frustum_y * 2.0 / r_view.height);
- Matrix4x4_Transform(&r_view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
+ VectorSet(temp, f[2], f[0] * f[2] * -RENDERSCENE.view.frustum_x * 2.0 / RENDERSCENE.view.width, f[1] * f[2] * -RENDERSCENE.view.frustum_y * 2.0 / RENDERSCENE.view.height);
+ Matrix4x4_Transform(&RENDERSCENE.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN));
}
//#311 vector (vector v) cs_project (EXT_CSQC)
float *f;
vec3_t v;
matrix4x4_t m;
+ const int prognum = PRVM_GetProgNr();
VM_SAFEPARMCOUNT(1, VM_CL_project);
f = PRVM_G_VECTOR(OFS_PARM0);
- Matrix4x4_Invert_Simple(&m, &r_view.matrix);
+ Matrix4x4_Invert_Simple(&m, &RENDERSCENE.view.matrix);
Matrix4x4_Transform(&m, f, v);
- VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_view.frustum_x*0.5*r_view.width, v[2]/v[0]/-r_view.frustum_y*r_view.height*0.5, v[0]);
+ VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-RENDERSCENE.view.frustum_x*0.5*RENDERSCENE.view.width, v[2]/v[0]/-RENDERSCENE.view.frustum_y*RENDERSCENE.view.height*0.5, v[0]);
}
//#330 float(float stnum) getstatf (EXT_CSQC)
unsigned char flags; //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
}vm_polygon_t;
-//static float vm_polygon_linewidth = 1;
-static mempool_t *vm_polygons_pool = NULL;
-static unsigned char vm_current_vertices = 0;
-static qboolean vm_polygons_initialized = false;
-static vm_polygon_t *vm_polygons = NULL;
-static unsigned long vm_polygons_num = 0, vm_drawpolygons_num = 0; //[515]: ok long on 64bit ?
-static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" check
+typedef struct vmpolygons_s
+{
+ //static float vm_polygon_linewidth = 1;
+ mempool_t *pool;
+ unsigned char current_vertices;
+ qboolean initialized;
+ vm_polygon_t *polygons;
+ unsigned long polygons_num, drawpolygons_num; //[515]: ok long on 64bit ?
+ qboolean polygonbegin; //[515]: for "no-crap-on-the-screen" check
+} vmpolygons_t;
+vmpolygons_t vmpolygons[PRVM_MAXPROGS];
#define VM_DEFPOLYNUM 64 //[515]: enough for default ?
#define VM_POLYGON_FL3V 16 //more than 2 vertices (used only for lines)
#define VM_POLYGON_FL2D 64
#define VM_POLYGON_FL4V 128 //4 vertices
-static void VM_InitPolygons (void)
+static void VM_InitPolygons (vmpolygons_t* polys)
{
- vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
- vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
- memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
- vm_polygons_num = VM_DEFPOLYNUM;
- vm_drawpolygons_num = 0;
- vm_polygonbegin = false;
- vm_polygons_initialized = true;
+ polys->pool = Mem_AllocPool("VMPOLY", 0, NULL);
+ polys->polygons = (vm_polygon_t *)Mem_Alloc(polys->pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+ memset(polys->polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+ polys->polygons_num = VM_DEFPOLYNUM;
+ polys->drawpolygons_num = 0;
+ polys->polygonbegin = false;
+ polys->initialized = true;
}
static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
// LordHavoc: FIXME: this is stupid code
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
- const vm_polygon_t *p = &vm_polygons[surfacelist[surfacelistindex]];
+ const vm_polygon_t *p = &polys->polygons[surfacelist[surfacelistindex]];
int flags = p->flags & 0x0f;
if(flags == DRAWFLAG_ADDITIVE)
{
drawqueuemesh_t mesh;
static int picelements[6] = {0, 1, 2, 0, 2, 3};
-
mesh.texture = p->tex;
mesh.data_element3i = picelements;
mesh.data_vertex3f = p->data;
void VM_CL_AddPolygonsToMeshQueue (void)
{
int i;
- if(!vm_drawpolygons_num)
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
+ if(!polys->drawpolygons_num)
return;
R_Mesh_Matrix(&identitymatrix);
GL_CullFace(GL_NONE);
- for(i = 0;i < (int)vm_drawpolygons_num;i++)
+ for(i = 0;i < (int)polys->drawpolygons_num;i++)
VM_DrawPolygonCallback(NULL, NULL, 1, &i);
- vm_drawpolygons_num = 0;
+ polys->drawpolygons_num = 0;
}
//void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon
-static void VM_CL_R_PolygonBegin (void)
+void VM_CL_R_PolygonBegin (void)
{
vm_polygon_t *p;
const char *picname;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin);
- if(!vm_polygons_initialized)
- VM_InitPolygons();
- if(vm_polygonbegin)
+ if(!polys->initialized)
+ VM_InitPolygons(polys);
+ if(polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n");
return;
}
- if(vm_drawpolygons_num >= vm_polygons_num)
+ if(polys->drawpolygons_num >= polys->polygons_num)
{
- p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
- Mem_Free(vm_polygons);
- vm_polygons = p;
- vm_polygons_num *= 2;
+ p = (vm_polygon_t *)Mem_Alloc(polys->pool, 2 * polys->polygons_num * sizeof(vm_polygon_t));
+ memset(p, 0, 2 * polys->polygons_num * sizeof(vm_polygon_t));
+ memcpy(p, polys->polygons, polys->polygons_num * sizeof(vm_polygon_t));
+ Mem_Free(polys->polygons);
+ polys->polygons = p;
+ polys->polygons_num *= 2;
}
- p = &vm_polygons[vm_drawpolygons_num];
+ p = &polys->polygons[polys->drawpolygons_num];
picname = PRVM_G_STRING(OFS_PARM0);
if(picname[0])
p->tex = Draw_CachePic(picname, true)->tex;
else
p->tex = r_texture_white;
p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
- vm_current_vertices = 0;
- vm_polygonbegin = true;
+ polys->current_vertices = 0;
+ polys->polygonbegin = true;
if(prog->argc >= 3)
{
if(PRVM_G_FLOAT(OFS_PARM2))
}
//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-static void VM_CL_R_PolygonVertex (void)
+void VM_CL_R_PolygonVertex (void)
{
float *coords, *tx, *rgb, alpha;
vm_polygon_t *p;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
- if(!vm_polygonbegin)
+ if(!polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
return;
rgb = PRVM_G_VECTOR(OFS_PARM2);
alpha = PRVM_G_FLOAT(OFS_PARM3);
- p = &vm_polygons[vm_drawpolygons_num];
- if(vm_current_vertices > 4)
+ p = &polys->polygons[polys->drawpolygons_num];
+ if(polys->current_vertices > 4)
{
VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n");
return;
}
- p->data[vm_current_vertices*3] = coords[0];
- p->data[1+vm_current_vertices*3] = coords[1];
- p->data[2+vm_current_vertices*3] = coords[2];
+ p->data[polys->current_vertices*3] = coords[0];
+ p->data[1+polys->current_vertices*3] = coords[1];
+ p->data[2+polys->current_vertices*3] = coords[2];
- p->data[12+vm_current_vertices*2] = tx[0];
+ p->data[12+polys->current_vertices*2] = tx[0];
if(!(p->flags & VM_POLYGON_FLLINES))
- p->data[13+vm_current_vertices*2] = tx[1];
+ p->data[13+polys->current_vertices*2] = tx[1];
- p->data[20+vm_current_vertices*4] = rgb[0];
- p->data[21+vm_current_vertices*4] = rgb[1];
- p->data[22+vm_current_vertices*4] = rgb[2];
- p->data[23+vm_current_vertices*4] = alpha;
+ p->data[20+polys->current_vertices*4] = rgb[0];
+ p->data[21+polys->current_vertices*4] = rgb[1];
+ p->data[22+polys->current_vertices*4] = rgb[2];
+ p->data[23+polys->current_vertices*4] = alpha;
- vm_current_vertices++;
- if(vm_current_vertices == 4)
+ polys->current_vertices++;
+ if(polys->current_vertices == 4)
p->flags |= VM_POLYGON_FL4V;
else
- if(vm_current_vertices == 3)
+ if(polys->current_vertices == 3)
p->flags |= VM_POLYGON_FL3V;
}
//void() R_EndPolygon
-static void VM_CL_R_PolygonEnd (void)
+void VM_CL_R_PolygonEnd (void)
{
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
- if(!vm_polygonbegin)
+ if(!polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
return;
}
- vm_polygonbegin = false;
- if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+ polys->polygonbegin = false;
+ if(polys->current_vertices > 2 || (polys->current_vertices >= 2 && polys->polygons[polys->drawpolygons_num].flags & VM_POLYGON_FLLINES))
{
- if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
- VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+ if(polys->polygons[polys->drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
+ VM_CL_AddPolygonTo2DScene(&polys->polygons[polys->drawpolygons_num]);
else
- vm_drawpolygons_num++;
+ polys->drawpolygons_num++;
}
else
- VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+ VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->current_vertices);
}
+static vmpolygons_t debugPolys;
+
void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
{
vm_polygon_t *p;
- if(!vm_polygons_initialized)
- VM_InitPolygons();
- if(vm_polygonbegin)
+ if(!debugPolys.initialized)
+ VM_InitPolygons(&debugPolys);
+ if(debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
return;
}
// limit polygons to a vaguely sane amount, beyond this each one just
// replaces the last one
- vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
- if(vm_drawpolygons_num >= vm_polygons_num)
+ debugPolys.drawpolygons_num = min(debugPolys.drawpolygons_num, (1<<20)-1);
+ if(debugPolys.drawpolygons_num >= debugPolys.polygons_num)
{
- p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
- Mem_Free(vm_polygons);
- vm_polygons = p;
- vm_polygons_num *= 2;
+ p = (vm_polygon_t *)Mem_Alloc(debugPolys.pool, 2 * debugPolys.polygons_num * sizeof(vm_polygon_t));
+ memset(p, 0, 2 * debugPolys.polygons_num * sizeof(vm_polygon_t));
+ memcpy(p, debugPolys.polygons, debugPolys.polygons_num * sizeof(vm_polygon_t));
+ Mem_Free(debugPolys.polygons);
+ debugPolys.polygons = p;
+ debugPolys.polygons_num *= 2;
}
- p = &vm_polygons[vm_drawpolygons_num];
+ p = &debugPolys.polygons[debugPolys.drawpolygons_num];
if(picname && picname[0])
p->tex = Draw_CachePic(picname, true)->tex;
else
p->tex = r_texture_white;
p->flags = flags;
- vm_current_vertices = 0;
- vm_polygonbegin = true;
+ debugPolys.current_vertices = 0;
+ debugPolys.polygonbegin = true;
if(draw2d)
p->flags |= VM_POLYGON_FL2D;
if(linewidth)
{
vm_polygon_t *p;
- if(!vm_polygonbegin)
+ if(!debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
return;
}
- p = &vm_polygons[vm_drawpolygons_num];
- if(vm_current_vertices > 4)
+ p = &debugPolys.polygons[debugPolys.drawpolygons_num];
+ if(debugPolys.current_vertices > 4)
{
Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
return;
}
- p->data[vm_current_vertices*3] = x;
- p->data[1+vm_current_vertices*3] = y;
- p->data[2+vm_current_vertices*3] = z;
+ p->data[debugPolys.current_vertices*3] = x;
+ p->data[1+debugPolys.current_vertices*3] = y;
+ p->data[2+debugPolys.current_vertices*3] = z;
- p->data[12+vm_current_vertices*2] = s;
+ p->data[12+debugPolys.current_vertices*2] = s;
if(!(p->flags & VM_POLYGON_FLLINES))
- p->data[13+vm_current_vertices*2] = t;
+ p->data[13+debugPolys.current_vertices*2] = t;
- p->data[20+vm_current_vertices*4] = r;
- p->data[21+vm_current_vertices*4] = g;
- p->data[22+vm_current_vertices*4] = b;
- p->data[23+vm_current_vertices*4] = a;
+ p->data[20+debugPolys.current_vertices*4] = r;
+ p->data[21+debugPolys.current_vertices*4] = g;
+ p->data[22+debugPolys.current_vertices*4] = b;
+ p->data[23+debugPolys.current_vertices*4] = a;
- vm_current_vertices++;
- if(vm_current_vertices == 4)
+ debugPolys.current_vertices++;
+ if(debugPolys.current_vertices == 4)
p->flags |= VM_POLYGON_FL4V;
else
- if(vm_current_vertices == 3)
+ if(debugPolys.current_vertices == 3)
p->flags |= VM_POLYGON_FL3V;
}
void Debug_PolygonEnd(void)
{
- if(!vm_polygonbegin)
+ if(!debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
return;
}
- vm_polygonbegin = false;
- if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+ debugPolys.polygonbegin = false;
+ if(debugPolys.current_vertices > 2 || (debugPolys.current_vertices >= 2 && debugPolys.polygons[debugPolys.drawpolygons_num].flags & VM_POLYGON_FLLINES))
{
- if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
- VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+ if(debugPolys.polygons[debugPolys.drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
+ VM_CL_AddPolygonTo2DScene(&debugPolys.polygons[debugPolys.drawpolygons_num]);
else
- vm_drawpolygons_num++;
+ debugPolys.drawpolygons_num++;
}
else
- Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+ Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.current_vertices);
}
/*
VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
-NULL, // #309
+NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC)
VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC)
NULL, // #312
const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
-void VM_CL_Cmd_Init(void)
+void VM_Polygons_Reset(void)
{
- VM_Cmd_Init();
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
// TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
- if(vm_polygons_initialized)
+ if(polys->initialized)
{
- Mem_FreePool(&vm_polygons_pool);
- vm_polygons_initialized = false;
+ Mem_FreePool(&polys->pool);
+ polys->initialized = false;
}
}
+void VM_CL_Cmd_Init(void)
+{
+ VM_Cmd_Init();
+ VM_Polygons_Reset();
+ renderscenes[PRVM_CLIENTPROG] = &client_scene;
+}
+
void VM_CL_Cmd_Reset(void)
{
VM_Cmd_Reset();
- if(vm_polygons_initialized)
- {
- Mem_FreePool(&vm_polygons_pool);
- vm_polygons_initialized = false;
- }
+ VM_Polygons_Reset();
}
int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex);
+/* These are VM built-ins that originate in the client-side programs support
+ but are reused by the other programs (usually the menu). */
+
+void VM_CL_setmodel (void);
+void VM_CL_precache_model (void);
+void VM_CL_setorigin (void);
+
+/* Per-VM scenes */
+extern renderscene_t* renderscenes[PRVM_MAXPROGS];
+
+void VM_CL_R_AddDynamicLight (void);
+void VM_CL_R_ClearScene (void);
+void VM_CL_R_AddEntities (void);
+void VM_CL_R_AddEntity (void);
+void VM_CL_R_SetView (void);
+void VM_CL_R_RenderScene (void);
+void VM_CL_R_LoadWorldModel (void);
+
+void VM_CL_R_PolygonBegin (void);
+void VM_CL_R_PolygonVertex (void);
+void VM_CL_R_PolygonEnd (void);
+/* VMs exposing the polygon calls must call this on Init/Reset */
+void VM_Polygons_Reset();
+
#endif /* __CLVM_CMDS_H__ */
}
extern cvar_t cl_noplayershadow;
-qboolean CSQC_AddRenderEdict(prvm_edict_t *ed)
+qboolean CSQC_AddRenderEdict(renderscene_t* scene, prvm_edict_t *ed)
{
int renderflags;
int c;
if (!model)
return false;
- e = CL_NewTempEntity();
+ e = CL_NewTempEntity(scene);
if (!e)
return false;
mempool_t *r_main_mempool;
rtexturepool_t *r_main_texturepool;
-//
-// screen size info
-//
-r_refdef_t r_refdef;
-r_view_t r_view;
-r_viewcache_t r_viewcache;
+renderscene_t client_scene;
cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "1", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
0, 1, 0
};
-extern void R_DrawModelShadows(void);
+extern void R_DrawModelShadows(renderscene_t* scene);
void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
{
//==================================================================================
-static void R_View_UpdateEntityVisible (void)
+static void R_View_UpdateEntityVisible (renderscene_t* scene)
{
int i, renderimask;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- renderimask = r_refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
- if (r_refdef.worldmodel && r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
+ renderimask = scene->refdef.envmap ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL) : ((chase_active.integer || r_waterstate.renderingscene) ? RENDER_VIEWMODEL : RENDER_EXTERIORMODEL);
+ if (scene->refdef.worldmodel && scene->refdef.worldmodel->brush.BoxTouchingVisibleLeafs)
{
// worldmodel can check visibility
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- ent = r_refdef.entities[i];
- r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || r_refdef.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.worldmodel, r_viewcache.world_leafvisible, ent->mins, ent->maxs));
+ ent = scene->refdef.entities[i];
+ scene->viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs)) && ((ent->effects & EF_NODEPTHTEST) || (ent->flags & RENDER_VIEWMODEL) || scene->refdef.worldmodel->brush.BoxTouchingVisibleLeafs(scene->refdef.worldmodel, scene->viewcache.world_leafvisible, ent->mins, ent->maxs));
}
if(r_cullentities_trace.integer && r_refdef.worldmodel->brush.TraceLineOfSight)
{
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- ent = r_refdef.entities[i];
- if(r_viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
+ ent = scene->refdef.entities[i];
+ if(scene->viewcache.entityvisible[i] && !(ent->effects & EF_NODEPTHTEST) && !(ent->flags & RENDER_VIEWMODEL) && !(ent->model && (ent->model->name[0] == '*')))
{
- if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, r_refdef.worldmodel, r_view.origin, ent->mins, ent->maxs))
+ if(Mod_CanSeeBox_Trace(r_cullentities_trace_samples.integer, r_cullentities_trace_enlarge.value, scene->refdef.worldmodel, scene->view.origin, ent->mins, ent->maxs))
ent->last_trace_visibility = realtime;
if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
- r_viewcache.entityvisible[i] = 0;
+ scene->viewcache.entityvisible[i] = 0;
}
}
}
else
{
// no worldmodel or it can't check visibility
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- ent = r_refdef.entities[i];
- r_viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
+ ent = scene->refdef.entities[i];
+ scene->viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
}
}
}
}
static void R_DrawNoModel(entity_render_t *ent);
-static void R_DrawModels(void)
+static void R_DrawModels(renderscene_t* scene)
{
int i;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- if (!r_viewcache.entityvisible[i])
+ if (!scene->viewcache.entityvisible[i])
continue;
- ent = r_refdef.entities[i];
- r_refdef.stats.entities++;
+ ent = scene->refdef.entities[i];
+ scene->refdef.stats.entities++;
if (ent->model && ent->model->Draw != NULL)
ent->model->Draw(ent);
else
}
}
-static void R_DrawModelsDepth(void)
+static void R_DrawModelsDepth(renderscene_t* scene)
{
int i;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- if (!r_viewcache.entityvisible[i])
+ if (!scene->viewcache.entityvisible[i])
continue;
- ent = r_refdef.entities[i];
+ ent = scene->refdef.entities[i];
if (ent->model && ent->model->DrawDepth != NULL)
ent->model->DrawDepth(ent);
}
}
-static void R_DrawModelsDebug(void)
+static void R_DrawModelsDebug(renderscene_t* scene)
{
int i;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- if (!r_viewcache.entityvisible[i])
+ if (!scene->viewcache.entityvisible[i])
continue;
- ent = r_refdef.entities[i];
+ ent = scene->refdef.entities[i];
if (ent->model && ent->model->DrawDebug != NULL)
ent->model->DrawDebug(ent);
}
}
-static void R_DrawModelsAddWaterPlanes(void)
+static void R_DrawModelsAddWaterPlanes(renderscene_t* scene)
{
int i;
entity_render_t *ent;
if (!r_drawentities.integer)
return;
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- if (!r_viewcache.entityvisible[i])
+ if (!scene->viewcache.entityvisible[i])
continue;
- ent = r_refdef.entities[i];
+ ent = scene->refdef.entities[i];
if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
ent->model->DrawAddWaterPlanes(ent);
}
}
-static void R_View_SetFrustum(void)
+static void R_View_SetFrustum(renderscene_t* scene)
{
int i;
double slopex, slopey;
// break apart the view matrix into vectors for various purposes
- Matrix4x4_ToVectors(&r_view.matrix, r_view.forward, r_view.left, r_view.up, r_view.origin);
- VectorNegate(r_view.left, r_view.right);
+ Matrix4x4_ToVectors(&scene->view.matrix, scene->view.forward, scene->view.left, scene->view.up, scene->view.origin);
+ VectorNegate(scene->view.left, scene->view.right);
#if 0
r_view.frustum[0].normal[0] = 0 - 1.0 / r_view.frustum_x;
r_view.frustum[5].dist = m[15] + m[14];
#endif
- if (r_view.useperspective)
+ if (scene->view.useperspective)
{
- slopex = 1.0 / r_view.frustum_x;
- slopey = 1.0 / r_view.frustum_y;
- VectorMA(r_view.forward, -slopex, r_view.left, r_view.frustum[0].normal);
- VectorMA(r_view.forward, slopex, r_view.left, r_view.frustum[1].normal);
- VectorMA(r_view.forward, -slopey, r_view.up , r_view.frustum[2].normal);
- VectorMA(r_view.forward, slopey, r_view.up , r_view.frustum[3].normal);
- VectorCopy(r_view.forward, r_view.frustum[4].normal);
+ slopex = 1.0 / scene->view.frustum_x;
+ slopey = 1.0 / scene->view.frustum_y;
+ VectorMA(scene->view.forward, -slopex, scene->view.left, scene->view.frustum[0].normal);
+ VectorMA(scene->view.forward, slopex, scene->view.left, scene->view.frustum[1].normal);
+ VectorMA(scene->view.forward, -slopey, scene->view.up , scene->view.frustum[2].normal);
+ VectorMA(scene->view.forward, slopey, scene->view.up , scene->view.frustum[3].normal);
+ VectorCopy(scene->view.forward, scene->view.frustum[4].normal);
// Leaving those out was a mistake, those were in the old code, and they
// fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
// I couldn't reproduce it after adding those normalizations. --blub
- VectorNormalize(r_view.frustum[0].normal);
- VectorNormalize(r_view.frustum[1].normal);
- VectorNormalize(r_view.frustum[2].normal);
- VectorNormalize(r_view.frustum[3].normal);
+ VectorNormalize(scene->view.frustum[0].normal);
+ VectorNormalize(scene->view.frustum[1].normal);
+ VectorNormalize(scene->view.frustum[2].normal);
+ VectorNormalize(scene->view.frustum[3].normal);
// calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[0]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, -1024 * slopey, r_view.up, r_view.frustumcorner[1]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, -1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[2]);
- VectorMAMAMAM(1, r_view.origin, 1024, r_view.forward, 1024 * slopex, r_view.left, 1024 * slopey, r_view.up, r_view.frustumcorner[3]);
+ VectorMAMAMAM(1, scene->view.origin, 1024, scene->view.forward, -1024 * slopex, scene->view.left, -1024 * slopey, scene->view.up, scene->view.frustumcorner[0]);
+ VectorMAMAMAM(1, scene->view.origin, 1024, scene->view.forward, 1024 * slopex, scene->view.left, -1024 * slopey, scene->view.up, scene->view.frustumcorner[1]);
+ VectorMAMAMAM(1, scene->view.origin, 1024, scene->view.forward, -1024 * slopex, scene->view.left, 1024 * slopey, scene->view.up, scene->view.frustumcorner[2]);
+ VectorMAMAMAM(1, scene->view.origin, 1024, scene->view.forward, 1024 * slopex, scene->view.left, 1024 * slopey, scene->view.up, scene->view.frustumcorner[3]);
- r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal);
- r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal);
- r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal);
- r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal);
- r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ scene->view.frustum[0].dist = DotProduct (scene->view.origin, scene->view.frustum[0].normal);
+ scene->view.frustum[1].dist = DotProduct (scene->view.origin, scene->view.frustum[1].normal);
+ scene->view.frustum[2].dist = DotProduct (scene->view.origin, scene->view.frustum[2].normal);
+ scene->view.frustum[3].dist = DotProduct (scene->view.origin, scene->view.frustum[3].normal);
+ scene->view.frustum[4].dist = DotProduct (scene->view.origin, scene->view.frustum[4].normal) + scene->refdef.nearclip;
}
else
{
- VectorScale(r_view.left, -r_view.ortho_x, r_view.frustum[0].normal);
- VectorScale(r_view.left, r_view.ortho_x, r_view.frustum[1].normal);
- VectorScale(r_view.up, -r_view.ortho_y, r_view.frustum[2].normal);
- VectorScale(r_view.up, r_view.ortho_y, r_view.frustum[3].normal);
- VectorCopy(r_view.forward, r_view.frustum[4].normal);
- r_view.frustum[0].dist = DotProduct (r_view.origin, r_view.frustum[0].normal) + r_view.ortho_x;
- r_view.frustum[1].dist = DotProduct (r_view.origin, r_view.frustum[1].normal) + r_view.ortho_x;
- r_view.frustum[2].dist = DotProduct (r_view.origin, r_view.frustum[2].normal) + r_view.ortho_y;
- r_view.frustum[3].dist = DotProduct (r_view.origin, r_view.frustum[3].normal) + r_view.ortho_y;
- r_view.frustum[4].dist = DotProduct (r_view.origin, r_view.frustum[4].normal) + r_refdef.nearclip;
+ VectorScale(scene->view.left, -scene->view.ortho_x, scene->view.frustum[0].normal);
+ VectorScale(scene->view.left, scene->view.ortho_x, scene->view.frustum[1].normal);
+ VectorScale(scene->view.up, -scene->view.ortho_y, scene->view.frustum[2].normal);
+ VectorScale(scene->view.up, scene->view.ortho_y, scene->view.frustum[3].normal);
+ VectorCopy(scene->view.forward, scene->view.frustum[4].normal);
+ scene->view.frustum[0].dist = DotProduct (scene->view.origin, scene->view.frustum[0].normal) + scene->view.ortho_x;
+ scene->view.frustum[1].dist = DotProduct (scene->view.origin, scene->view.frustum[1].normal) + scene->view.ortho_x;
+ scene->view.frustum[2].dist = DotProduct (scene->view.origin, scene->view.frustum[2].normal) + scene->view.ortho_y;
+ scene->view.frustum[3].dist = DotProduct (scene->view.origin, scene->view.frustum[3].normal) + scene->view.ortho_y;
+ scene->view.frustum[4].dist = DotProduct (scene->view.origin, scene->view.frustum[4].normal) + r_refdef.nearclip;
}
- r_view.numfrustumplanes = 5;
+ scene->view.numfrustumplanes = 5;
- if (r_view.useclipplane)
+ if (scene->view.useclipplane)
{
- r_view.numfrustumplanes = 6;
- r_view.frustum[5] = r_view.clipplane;
+ scene->view.numfrustumplanes = 6;
+ scene->view.frustum[5] = scene->view.clipplane;
}
- for (i = 0;i < r_view.numfrustumplanes;i++)
- PlaneClassify(r_view.frustum + i);
+ for (i = 0;i < scene->view.numfrustumplanes;i++)
+ PlaneClassify(scene->view.frustum + i);
// LordHavoc: note to all quake engine coders, Quake had a special case
// for 90 degrees which assumed a square view (wrong), so I removed it,
//PlaneClassify(&frustum[4]);
}
-void R_View_Update(void)
+void R_View_Update(renderscene_t* scene)
{
- R_View_SetFrustum();
- R_View_WorldVisibility(r_view.useclipplane);
- R_View_UpdateEntityVisible();
+ R_View_SetFrustum(scene);
+ R_View_WorldVisibility(scene->view.useclipplane);
+ R_View_UpdateEntityVisible(scene);
}
-void R_SetupView(void)
+void R_SetupView(renderscene_t* scene)
{
- if (!r_view.useperspective)
- GL_SetupView_Mode_Ortho(-r_view.ortho_x, -r_view.ortho_y, r_view.ortho_x, r_view.ortho_y, -r_refdef.farclip, r_refdef.farclip);
- else if (r_refdef.rtworldshadows || r_refdef.rtdlightshadows)
- GL_SetupView_Mode_PerspectiveInfiniteFarClip(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip);
+ if (!scene->view.useperspective)
+ GL_SetupView_Mode_Ortho(-scene->view.ortho_x, -scene->view.ortho_y, scene->view.ortho_x, scene->view.ortho_y, -scene->refdef.farclip, scene->refdef.farclip);
+ else if (scene->refdef.rtworldshadows || scene->refdef.rtdlightshadows)
+ GL_SetupView_Mode_PerspectiveInfiniteFarClip(scene->view.frustum_x, scene->view.frustum_y, scene->refdef.nearclip);
else
- GL_SetupView_Mode_Perspective(r_view.frustum_x, r_view.frustum_y, r_refdef.nearclip, r_refdef.farclip);
+ GL_SetupView_Mode_Perspective(scene->view.frustum_x, scene->view.frustum_y, scene->refdef.nearclip, scene->refdef.farclip);
- GL_SetupView_Orientation_FromEntity(&r_view.matrix);
+ GL_SetupView_Orientation_FromEntity(&scene->view.matrix);
- if (r_view.useclipplane)
+ if (scene->view.useclipplane)
{
// LordHavoc: couldn't figure out how to make this approach the
- vec_t dist = r_view.clipplane.dist - r_water_clippingplanebias.value;
- vec_t viewdist = DotProduct(r_view.origin, r_view.clipplane.normal);
- if (viewdist < r_view.clipplane.dist + r_water_clippingplanebias.value)
- dist = r_view.clipplane.dist;
- GL_SetupView_ApplyCustomNearClipPlane(r_view.clipplane.normal[0], r_view.clipplane.normal[1], r_view.clipplane.normal[2], dist);
+ vec_t dist = scene->view.clipplane.dist - r_water_clippingplanebias.value;
+ vec_t viewdist = DotProduct(scene->view.origin, scene->view.clipplane.normal);
+ if (viewdist < scene->view.clipplane.dist + r_water_clippingplanebias.value)
+ dist = scene->view.clipplane.dist;
+ GL_SetupView_ApplyCustomNearClipPlane(scene->view.clipplane.normal[0], scene->view.clipplane.normal[1], scene->view.clipplane.normal[2], dist);
}
}
GL_CullFace(GL_FRONT); // quake is backwards, this culls back faces
}
-void R_ResetViewRendering3D(void)
+void R_ResetViewRendering3D(renderscene_t* scene)
{
if (gl_support_fragment_shader)
{
DrawQ_Finish();
// GL is weird because it's bottom to top, r_view.y is top to bottom
- qglViewport(r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
- R_SetupView();
- GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ qglViewport(scene->view.x, vid.height - (scene->view.y + scene->view.height), scene->view.width, scene->view.height);CHECKGLERROR
+ R_SetupView(scene);
+ GL_Scissor(scene->view.x, scene->view.y, scene->view.width, scene->view.height);
GL_Color(1, 1, 1, 1);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_ColorMask(scene->view.colormask[0], scene->view.colormask[1], scene->view.colormask[2], 1);
GL_BlendFunc(GL_ONE, GL_ZERO);
GL_AlphaTest(false);
GL_ScissorTest(true);
GL_DepthTest(true);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
- GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
+ GL_PolygonOffset(scene->refdef.polygonfactor, scene->refdef.polygonoffset);
qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
qglDepthFunc(GL_LEQUAL);CHECKGLERROR
qglDisable(GL_STENCIL_TEST);CHECKGLERROR
qglStencilMask(~0);CHECKGLERROR
qglStencilFunc(GL_ALWAYS, 128, ~0);CHECKGLERROR
qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);CHECKGLERROR
- GL_CullFace(r_view.cullface_back);
+ GL_CullFace(scene->view.cullface_back);
}
/*
"#endif // FRAGMENT_SHADER\n"
*/
-void R_RenderScene(qboolean addwaterplanes);
+void R_RenderScene(renderscene_t* scene, qboolean addwaterplanes);
static void R_Water_StartFrame(void)
{
}
}
-static void R_Water_ProcessPlanes(void)
+static void R_Water_ProcessPlanes(renderscene_t* scene)
{
r_view_t originalview;
int planeindex;
r_waterstate_waterplane_t *p;
- originalview = r_view;
+ originalview = scene->view;
// make sure enough textures are allocated
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
// render views
for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
{
- r_view.showdebug = false;
- r_view.width = r_waterstate.waterwidth;
- r_view.height = r_waterstate.waterheight;
- r_view.useclipplane = true;
+ scene->view.showdebug = false;
+ scene->view.width = r_waterstate.waterwidth;
+ scene->view.height = r_waterstate.waterheight;
+ scene->view.useclipplane = true;
r_waterstate.renderingscene = true;
// render the normal view scene and copy into texture
// (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
{
- r_view.clipplane = p->plane;
- VectorNegate(r_view.clipplane.normal, r_view.clipplane.normal);
- r_view.clipplane.dist = -r_view.clipplane.dist;
- PlaneClassify(&r_view.clipplane);
+ scene->view.clipplane = p->plane;
+ VectorNegate(scene->view.clipplane.normal, scene->view.clipplane.normal);
+ scene->view.clipplane.dist = -scene->view.clipplane.dist;
+ PlaneClassify(&scene->view.clipplane);
- R_RenderScene(false);
+ R_RenderScene(scene, false);
// copy view into the screen texture
R_Mesh_TexBind(0, R_GetTexture(p->texture_refraction));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, scene->view.x, vid.height - (scene->view.y + scene->view.height), scene->view.width, scene->view.height);CHECKGLERROR
}
if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
{
// render reflected scene and copy into texture
- Matrix4x4_Reflect(&r_view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
- r_view.clipplane = p->plane;
+ Matrix4x4_Reflect(&scene->view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
+ scene->view.clipplane = p->plane;
// reverse the cullface settings for this render
- r_view.cullface_front = GL_FRONT;
- r_view.cullface_back = GL_BACK;
- if (r_refdef.worldmodel && r_refdef.worldmodel->brush.num_pvsclusterbytes)
+ scene->view.cullface_front = GL_FRONT;
+ scene->view.cullface_back = GL_BACK;
+ if (scene->refdef.worldmodel && scene->refdef.worldmodel->brush.num_pvsclusterbytes)
{
- r_view.usecustompvs = true;
+ scene->view.usecustompvs = true;
if (p->pvsvalid)
- memcpy(r_viewcache.world_pvsbits, p->pvsbits, r_refdef.worldmodel->brush.num_pvsclusterbytes);
+ memcpy(scene->viewcache.world_pvsbits, p->pvsbits, scene->refdef.worldmodel->brush.num_pvsclusterbytes);
else
- memset(r_viewcache.world_pvsbits, 0xFF, r_refdef.worldmodel->brush.num_pvsclusterbytes);
+ memset(scene->viewcache.world_pvsbits, 0xFF, scene->refdef.worldmodel->brush.num_pvsclusterbytes);
}
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("viewclear");
- R_RenderScene(false);
+ R_RenderScene(scene, false);
R_Mesh_TexBind(0, R_GetTexture(p->texture_reflection));
GL_ActiveTexture(0);
CHECKGLERROR
- qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, r_view.x, vid.height - (r_view.y + r_view.height), r_view.width, r_view.height);CHECKGLERROR
+ qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, scene->view.x, vid.height - (scene->view.y + scene->view.height), scene->view.width, scene->view.height);CHECKGLERROR
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("viewclear");
}
- r_view = originalview;
- r_view.clear = true;
+ scene->view = originalview;
+ scene->view.clear = true;
r_waterstate.renderingscene = false;
}
return;
error:
- r_view = originalview;
+ scene->view = originalview;
r_waterstate.renderingscene = false;
Cvar_SetValueQuick(&r_water, 0);
Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed! Turned off r_water.\n");
}
}
-void R_HDR_RenderBloomTexture(void)
+void R_HDR_RenderBloomTexture(renderscene_t* scene)
{
int oldwidth, oldheight;
float oldcolorscale;
- oldcolorscale = r_view.colorscale;
- oldwidth = r_view.width;
- oldheight = r_view.height;
- r_view.width = r_bloomstate.bloomwidth;
- r_view.height = r_bloomstate.bloomheight;
+ oldcolorscale = scene->view.colorscale;
+ oldwidth = scene->view.width;
+ oldheight = scene->view.height;
+ scene->view.width = r_bloomstate.bloomwidth;
+ scene->view.height = r_bloomstate.bloomheight;
// TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer? it might improve SLI performance.
// TODO: add exposure compensation features
// TODO: add fp16 framebuffer support
- r_view.showdebug = false;
- r_view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
+ scene->view.showdebug = false;
+ scene->view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("HDRclear");
r_waterstate.numwaterplanes = 0;
- R_RenderScene(r_waterstate.enabled);
- r_view.showdebug = true;
+ R_RenderScene(scene, r_waterstate.enabled);
+ scene->view.showdebug = true;
R_ResetViewRendering2D();
R_Bloom_MakeTexture();
// restore the view settings
- r_view.width = oldwidth;
- r_view.height = oldheight;
- r_view.colorscale = oldcolorscale;
+ scene->view.width = oldwidth;
+ scene->view.height = oldheight;
+ scene->view.colorscale = oldcolorscale;
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
}
}
-void R_RenderScene(qboolean addwaterplanes);
-
matrix4x4_t r_waterscrollmatrix;
void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
}
}
-void R_UpdateVariables(void)
+void R_UpdateVariables(renderscene_t* scene)
{
R_Textures_Frame();
- r_refdef.farclip = 4096;
- if (r_refdef.worldmodel)
- r_refdef.farclip += VectorDistance(r_refdef.worldmodel->normalmins, r_refdef.worldmodel->normalmaxs);
- r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
+ scene->refdef.farclip = 4096;
+ if (scene->refdef.worldmodel)
+ scene->refdef.farclip += VectorDistance(scene->refdef.worldmodel->normalmins, scene->refdef.worldmodel->normalmaxs);
+ scene->refdef.nearclip = bound (0.001f, r_nearclip.value, scene->refdef.farclip - 1.0f);
if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
- r_refdef.polygonfactor = 0;
- r_refdef.polygonoffset = 0;
- r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
- r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
-
- r_refdef.rtworld = r_shadow_realtime_world.integer;
- r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
- r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
- r_refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
- r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
+ scene->refdef.polygonfactor = 0;
+ scene->refdef.polygonoffset = 0;
+ scene->refdef.shadowpolygonfactor = scene->refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+ scene->refdef.shadowpolygonoffset = scene->refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
+
+ scene->refdef.rtworld = r_shadow_realtime_world.integer;
+ scene->refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
+ scene->refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
+ scene->refdef.rtdlightshadows = r_refdef.rtdlight && r_shadow_realtime_dlight_shadows.integer && gl_stencil;
+ scene->refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
if (r_showsurfaces.integer)
{
- r_refdef.rtworld = false;
- r_refdef.rtworldshadows = false;
- r_refdef.rtdlight = false;
- r_refdef.rtdlightshadows = false;
- r_refdef.lightmapintensity = 0;
+ scene->refdef.rtworld = false;
+ scene->refdef.rtworldshadows = false;
+ scene->refdef.rtdlight = false;
+ scene->refdef.rtdlightshadows = false;
+ scene->refdef.lightmapintensity = 0;
}
if (gamemode == GAME_NEHAHRA)
{
if (gl_fogenable.integer)
{
- r_refdef.oldgl_fogenable = true;
- r_refdef.fog_density = gl_fogdensity.value;
- r_refdef.fog_red = gl_fogred.value;
- r_refdef.fog_green = gl_foggreen.value;
- r_refdef.fog_blue = gl_fogblue.value;
- r_refdef.fog_alpha = 1;
- r_refdef.fog_start = 0;
- r_refdef.fog_end = gl_skyclip.value;
+ scene->refdef.oldgl_fogenable = true;
+ scene->refdef.fog_density = gl_fogdensity.value;
+ scene->refdef.fog_red = gl_fogred.value;
+ scene->refdef.fog_green = gl_foggreen.value;
+ scene->refdef.fog_blue = gl_fogblue.value;
+ scene->refdef.fog_alpha = 1;
+ scene->refdef.fog_start = 0;
+ scene->refdef.fog_end = gl_skyclip.value;
}
- else if (r_refdef.oldgl_fogenable)
+ else if (scene->refdef.oldgl_fogenable)
{
- r_refdef.oldgl_fogenable = false;
- r_refdef.fog_density = 0;
- r_refdef.fog_red = 0;
- r_refdef.fog_green = 0;
- r_refdef.fog_blue = 0;
- r_refdef.fog_alpha = 0;
- r_refdef.fog_start = 0;
- r_refdef.fog_end = 0;
+ scene->refdef.oldgl_fogenable = false;
+ scene->refdef.fog_density = 0;
+ scene->refdef.fog_red = 0;
+ scene->refdef.fog_green = 0;
+ scene->refdef.fog_blue = 0;
+ scene->refdef.fog_alpha = 0;
+ scene->refdef.fog_start = 0;
+ scene->refdef.fog_end = 0;
}
}
- r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
- r_refdef.fog_start = max(0, r_refdef.fog_start);
- r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
+ scene->refdef.fog_alpha = bound(0, scene->refdef.fog_alpha, 1);
+ scene->refdef.fog_start = max(0, scene->refdef.fog_start);
+ scene->refdef.fog_end = max(scene->refdef.fog_start + 0.01, scene->refdef.fog_end);
// R_UpdateFogColor(); // why? R_RenderScene does it anyway
- if (r_refdef.fog_density)
+ if (scene->refdef.fog_density)
{
- r_refdef.fogenabled = true;
+ scene->refdef.fogenabled = true;
// this is the point where the fog reaches 0.9986 alpha, which we
// consider a good enough cutoff point for the texture
// (0.9986 * 256 == 255.6)
if (r_fog_exp2.integer)
- r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
+ scene->refdef.fogrange = 32 / (scene->refdef.fog_density * scene->refdef.fog_density) + scene->refdef.fog_start;
else
- r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
- r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
- r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
- r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
+ scene->refdef.fogrange = 2048 / scene->refdef.fog_density + scene->refdef.fog_start;
+ scene->refdef.fogrange = bound(scene->refdef.fog_start, scene->refdef.fogrange, scene->refdef.fog_end);
+ scene->refdef.fograngerecip = 1.0f / scene->refdef.fogrange;
+ scene->refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * scene->refdef.fograngerecip;
// fog color was already set
// update the fog texture
- if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
- R_BuildFogTexture();
+ if (scene->refdef.fogmasktable_start != scene->refdef.fog_start || scene->refdef.fogmasktable_alpha != scene->refdef.fog_alpha || scene->refdef.fogmasktable_density != scene->refdef.fog_density || scene->refdef.fogmasktable_range != scene->refdef.fogrange)
+ R_BuildFogTexture(scene);
}
else
- r_refdef.fogenabled = false;
+ scene->refdef.fogenabled = false;
}
/*
R_RenderView
================
*/
-void R_RenderView(void)
+void R_RenderView(renderscene_t* scene)
{
- if (!r_refdef.entities/* || !r_refdef.worldmodel*/)
+ if (!scene->refdef.entities/* || !r_refdef.worldmodel*/)
return; //Host_Error ("R_RenderView: NULL worldmodel");
r_view.colorscale = r_hdr_scenebrightness.value;
if (r_timereport_active)
R_TimeReport("viewsetup");
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
- if (r_view.clear || r_refdef.fogenabled)
+ if (scene->view.clear || scene->refdef.fogenabled)
{
R_ClearScreen(r_refdef.fogenabled);
if (r_timereport_active)
R_TimeReport("viewclear");
}
- r_view.clear = true;
+ scene->view.clear = true;
- r_view.showdebug = true;
+ scene->view.showdebug = true;
// this produces a bloom texture to be used in R_BlendView() later
if (r_hdr.integer)
- R_HDR_RenderBloomTexture();
+ R_HDR_RenderBloomTexture(scene);
r_waterstate.numwaterplanes = 0;
- R_RenderScene(r_waterstate.enabled);
+ R_RenderScene(scene, r_waterstate.enabled);
R_BlendView();
if (r_timereport_active)
extern cvar_t cl_locs_show;
static void R_DrawLocs(void);
static void R_DrawEntityBBoxes(void);
-void R_RenderScene(qboolean addwaterplanes)
+void R_RenderScene(renderscene_t* scene, qboolean addwaterplanes)
{
Matrix4x4_Invert_Simple(&r_view.inverse_matrix, &r_view.matrix);
R_UpdateFogColor();
if (addwaterplanes)
{
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
- R_View_Update();
+ R_View_Update(scene);
if (r_timereport_active)
R_TimeReport("watervis");
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- R_DrawModelsAddWaterPlanes();
+ R_DrawModelsAddWaterPlanes(scene);
if (r_timereport_active)
R_TimeReport("watermodels");
- R_Water_ProcessPlanes();
+ R_Water_ProcessPlanes(scene);
if (r_timereport_active)
R_TimeReport("waterscenes");
}
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
// don't let sound skip if going slow
if (r_refdef.extraupdate)
R_SkyStartFrame();
- R_View_Update();
+ R_View_Update(scene);
if (r_timereport_active)
R_TimeReport("visibility");
}
if (r_depthfirst.integer >= 2)
{
- R_DrawModelsDepth();
+ R_DrawModelsDepth(scene);
if (r_timereport_active)
R_TimeReport("modeldepth");
}
if (r_refdef.extraupdate)
S_ExtraUpdate ();
- R_DrawModels();
+ R_DrawModels(scene);
if (r_timereport_active)
R_TimeReport("models");
if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
{
- R_DrawModelShadows();
+ R_DrawModelShadows(scene);
- R_ResetViewRendering3D();
+ R_ResetViewRendering3D(scene);
// don't let sound skip if going slow
if (r_refdef.extraupdate)
r_refdef.worldmodel->DrawDebug(r_refdef.worldentity);
if (r_timereport_active)
R_TimeReport("worlddebug");
- R_DrawModelsDebug();
+ R_DrawModelsDebug(scene);
if (r_timereport_active)
R_TimeReport("modeldebug");
}
PRVM_End;
}
+extern renderscene_t menu_renderscene;
+
void MP_Draw (void)
{
PRVM_Begin;
PRVM_SetProg(PRVM_MENUPROG);
+ // Here?
+ R_UpdateVariables (&menu_renderscene);
+
PRVM_ExecuteProgram(prog->funcoffsets.m_draw,"m_draw() required");
PRVM_End;
MR_SetRouting (TRUE);
else
MR_SetRouting (FALSE);
+
+ // FIXME: needed so cl.max_entities is set
+ CL_ClearState ();
}
#include "quakedef.h"
#include "prvm_cmds.h"
+#include "clvm_cmds.h"
#include "menu.h"
//============================================================================
#ifdef SUPPORT_GECKO
"DP_GECKO_SUPPORT "
#endif
+"DP_QC_RENDER_SCENE"
;
/*
VM_findflags, // #87
VM_findchainflags, // #88
VM_cvar_defstring, // #89
-NULL, // #90
-NULL, // #91
-NULL, // #92
+VM_CL_setmodel, // #90 void(entity e, string m) setmodel (QUAKE)
+VM_CL_precache_model, // #91 void(string s) precache_model (QUAKE)
+VM_CL_setorigin, // #92 void(entity e, vector o) setorigin (QUAKE)
NULL, // #93
NULL, // #94
NULL, // #95
NULL, // #297
NULL, // #298
NULL, // #299
-NULL, // #300
-NULL, // #301
-NULL, // #302
-NULL, // #303
-NULL, // #304
-NULL, // #305
-NULL, // #306
-NULL, // #307
-NULL, // #308
-NULL, // #309
+// CSQC range #300-#399
+VM_CL_R_ClearScene, // #300 void() clearscene (DP_QC_RENDER_SCENE)
+VM_CL_R_AddEntities, // #301 void(float mask) addentities (DP_QC_RENDER_SCENE)
+VM_CL_R_AddEntity, // #302 void(entity ent) addentity (DP_QC_RENDER_SCENE)
+VM_CL_R_SetView, // #303 float(float property, ...) setproperty (DP_QC_RENDER_SCENE)
+VM_CL_R_RenderScene, // #304 void() renderscene (DP_QC_RENDER_SCENE)
+VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (DP_QC_RENDER_SCENE)
+VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
+VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
+VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
+NULL/*VM_CL_R_LoadWorldModel*/, // #309 void(string modelname) R_LoadWorldModel
NULL, // #310
NULL, // #311
NULL, // #312
const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t);
+renderscene_t menu_renderscene;
+
void VM_M_Cmd_Init(void)
{
VM_Cmd_Init();
+ VM_Polygons_Reset();
+ renderscenes[PRVM_MENUPROG] = &menu_renderscene;
+ memset (&menu_renderscene, 0, sizeof (renderscene_t));
+
+ menu_renderscene.refdef.frustumscale_x = 1;
+ menu_renderscene.refdef.frustumscale_y = 1;
+ menu_renderscene.refdef.maxentities = MAX_EDICTS + 256 + 512;
+ menu_renderscene.refdef.entities = (entity_render_t **)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t *) * menu_renderscene.refdef.maxentities);
+
+ menu_renderscene.view.width = vid.width;
+ menu_renderscene.view.height = vid.height;
+ menu_renderscene.view.depth = 1;
+ menu_renderscene.view.x = 0;
+ menu_renderscene.view.y = 0;
+ menu_renderscene.view.z = 0;
+ menu_renderscene.view.colormask[0] = true;
+ menu_renderscene.view.colormask[1] = true;
+ menu_renderscene.view.colormask[2] = true;
+ menu_renderscene.view.colormask[3] = true;
+
+ menu_renderscene.view.useperspective = true;
+ menu_renderscene.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0);
+ menu_renderscene.view.frustum_x = r_view.frustum_y * (float)menu_renderscene.view.width / (float)menu_renderscene.view.height / vid_pixelheight.value;
}
void VM_M_Cmd_Reset(void)
{
//VM_Cmd_Init();
VM_Cmd_Reset();
+ VM_Polygons_Reset();
}
extern void R_SetupView(void);
extern cvar_t r_shadows_throwdistance;
-void R_DrawModelShadows(void)
+void R_DrawModelShadows(renderscene_t* scene)
{
int i;
float relativethrowdistance;
return;
CHECKGLERROR
- GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
+ GL_Scissor(scene->view.x, scene->view.y, scene->view.width, scene->view.height);
r_shadow_rendermode = R_SHADOW_RENDERMODE_NONE;
R_Shadow_RenderMode_StencilShadowVolumes(true);
- for (i = 0;i < r_refdef.numentities;i++)
+ for (i = 0;i < scene->refdef.numentities;i++)
{
- ent = r_refdef.entities[i];
+ ent = scene->refdef.entities[i];
// cast shadows from anything that is not a submodel of the map
if (ent->model && ent->model->DrawShadowVolume != NULL && !ent->model->brush.submodel && (ent->flags & RENDER_SHADOW))
{
// set up ortho view for rendering this pass
GL_SetupView_Mode_Ortho(0, 0, 1, 1, -10, 100);
- GL_Scissor(r_view.x, r_view.y, r_view.width, r_view.height);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_Scissor(scene->view.x, scene->view.y, scene->view.width, scene->view.height);
+ GL_ColorMask(scene->view.colormask[0], scene->view.colormask[1], scene->view.colormask[2], 1);
GL_ScissorTest(true);
R_Mesh_Matrix(&identitymatrix);
R_Mesh_ResetTextureState();
GL_DepthMask(false);
GL_PolygonOffset(0, 0);CHECKGLERROR
GL_Color(0, 0, 0, 0.5);
- GL_ColorMask(r_view.colormask[0], r_view.colormask[1], r_view.colormask[2], 1);
+ GL_ColorMask(scene->view.colormask[0], scene->view.colormask[1], scene->view.colormask[2], 1);
qglDepthFunc(GL_ALWAYS);CHECKGLERROR
qglEnable(GL_STENCIL_TEST);CHECKGLERROR
qglStencilMask(~0);CHECKGLERROR
extern cvar_t r_dynamic;
void R_Init(void);
-void R_UpdateVariables(void); // must call after setting up most of r_refdef, but before calling R_RenderView
-void R_RenderView(void); // must set r_refdef and call R_UpdateVariables first
+void R_UpdateVariables(renderscene_t* scene); // must call after setting up most of r_refdef, but before calling R_RenderView
+void R_RenderView(renderscene_t* scene); // must set r_refdef and call R_UpdateVariables first
void R_InitSky (unsigned char *src, int bytesperpixel); // called at level load