From afca12bb45e127f8c06427deaba55d766b0c9342 Mon Sep 17 00:00:00 2001 From: res Date: Fri, 4 Jan 2008 19:12:11 +0000 Subject: [PATCH] - Instead of global refdef, view and viewcache variables they're now encapsulated in a struct 'renderscene'. - Each program type got a renderscene. - Changed multiple methods to not use the global refdef etc. but take a renderscene instead. - Made multiple CSQC builtin implementations non-static to allow access from MQC. git-svn-id: svn://svn.icculus.org/twilight/branches/dp-mqc-render/darkplaces@7902 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 27 ++-- cl_screen.c | 10 +- client.h | 23 ++- clvm_cmds.c | 353 ++++++++++++++++++++++++------------------- clvm_cmds.h | 24 +++ csprogs.c | 4 +- gl_rmain.c | 425 ++++++++++++++++++++++++++-------------------------- menu.c | 8 + mvm_cmds.c | 55 +++++-- r_shadow.c | 14 +- render.h | 4 +- 11 files changed, 529 insertions(+), 418 deletions(-) diff --git a/cl_main.c b/cl_main.c index 44c156ea..01988412 100644 --- a/cl_main.c +++ b/cl_main.c @@ -607,17 +607,17 @@ void CL_ClearTempEntities (void) 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); @@ -845,7 +845,7 @@ void CL_AddQWCTFFlagModel(entity_t *player, int skin) } // end of code taken from QuakeWorld - flag = CL_NewTempEntity(); + flag = CL_NewTempEntity(&client_scene); if (!flag) return; @@ -1552,7 +1552,7 @@ static void CL_RelinkEffects(void) // 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; @@ -1676,7 +1676,7 @@ void CL_RelinkBeams(void) d = VectorNormalizeLength(dist); while (d > 0) { - ent = CL_NewTempEntity (); + ent = CL_NewTempEntity (&client_scene); if (!ent) return; //VectorCopy (org, ent->render.origin); @@ -1708,7 +1708,7 @@ static void CL_RelinkQWNails(void) // 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 @@ -2236,15 +2236,20 @@ void CL_Shutdown (void) 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 (); diff --git a/cl_screen.c b/cl_screen.c index 7eb8bf88..94eaf837 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -1710,7 +1710,7 @@ static void R_Envmap_f (void) r_refdef.envmap = true; - R_UpdateVariables(); + R_UpdateVariables (&client_scene); r_view.x = 0; r_view.y = 0; @@ -1733,7 +1733,7 @@ static void R_Envmap_f (void) 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); } @@ -1900,7 +1900,7 @@ void SCR_DrawScreen (void) R_TimeReport_BeginFrame(); - R_UpdateVariables(); + R_UpdateVariables (&client_scene); // Quake uses clockwise winding, so these are swapped r_view.cullface_front = GL_BACK; @@ -1948,7 +1948,7 @@ void SCR_DrawScreen (void) r_view.frustum_y *= r_refdef.frustumscale_y; if(!CL_VM_UpdateView()) - R_RenderView(); + R_RenderView(&client_scene); if (scr_zoomwindow.integer) { @@ -1969,7 +1969,7 @@ void SCR_DrawScreen (void) r_view.frustum_y *= r_refdef.frustumscale_y; if(!CL_VM_UpdateView()) - R_RenderView(); + R_RenderView(&client_scene); } } diff --git a/client.h b/client.h index 0e3163d1..1aa55989 100644 --- a/client.h +++ b/client.h @@ -1168,7 +1168,8 @@ void CL_Beam_CalculatePositions (const beam_t *b, vec3_t start, vec3_t end); 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); @@ -1511,9 +1512,23 @@ typedef struct r_viewcache_s } 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 diff --git a/clvm_cmds.c b/clvm_cmds.c index e21d090d..c39b82c3 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -5,6 +5,10 @@ #include "cl_collision.h" #include "r_shadow.h" +/* Per-VM scenes */ +renderscene_t* renderscenes[PRVM_MAXPROGS]; +#define RENDERSCENE (*renderscenes[prognum]) + //============================================================================ // Client //[515]: unsolved PROBLEMS @@ -39,7 +43,7 @@ static void VM_CL_makevectors (void) } // #2 void(entity e, vector o) setorigin -static void VM_CL_setorigin (void) +void VM_CL_setorigin (void) { prvm_edict_t *e; float *org; @@ -62,7 +66,7 @@ static void VM_CL_setorigin (void) } // #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; @@ -339,7 +343,7 @@ static void VM_CL_tracetoss (void) // #20 void(string s) precache_model -static void VM_CL_precache_model (void) +void VM_CL_precache_model (void) { const char *name; int i; @@ -636,38 +640,41 @@ static void VM_CL_getlight (void) //============================================================================ //[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; @@ -678,10 +685,12 @@ static void VM_CL_R_ClearScene (void) //#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); @@ -702,23 +711,26 @@ static void VM_CL_R_AddEntities (void) 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); @@ -729,41 +741,41 @@ static void VM_CL_R_SetView (void) 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); @@ -819,7 +831,7 @@ static void VM_CL_R_SetView (void) 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; @@ -830,31 +842,35 @@ static void VM_CL_R_SetView (void) } //#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); } //============================================================================ @@ -864,11 +880,12 @@ static void VM_CL_unproject (void) { 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) @@ -877,12 +894,13 @@ static void VM_CL_project (void) 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) @@ -2239,13 +2257,17 @@ typedef struct 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) @@ -2253,24 +2275,26 @@ static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" #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) @@ -2345,7 +2369,6 @@ static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p) { 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; @@ -2370,47 +2393,51 @@ static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p) 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)) @@ -2424,13 +2451,15 @@ static void VM_CL_R_PolygonBegin (void) } //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; @@ -2440,86 +2469,90 @@ static void VM_CL_R_PolygonVertex (void) 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) @@ -2533,57 +2566,57 @@ void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, f { 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); } /* @@ -3163,7 +3196,7 @@ VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcol 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 @@ -3367,24 +3400,28 @@ NULL, // #499 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(); } diff --git a/clvm_cmds.h b/clvm_cmds.h index 58928c2f..2e5ca5cb 100644 --- a/clvm_cmds.h +++ b/clvm_cmds.h @@ -3,4 +3,28 @@ 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__ */ diff --git a/csprogs.c b/csprogs.c index ada3b073..9809b5ea 100644 --- a/csprogs.c +++ b/csprogs.c @@ -123,7 +123,7 @@ void CSQC_Think (prvm_edict_t *ed) } 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; @@ -137,7 +137,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) if (!model) return false; - e = CL_NewTempEntity(); + e = CL_NewTempEntity(scene); if (!e) return false; diff --git a/gl_rmain.c b/gl_rmain.c index 3e4ec056..6c41e117 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -28,12 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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" }; @@ -208,7 +203,7 @@ const static float r_screenvertex3f[12] = 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) { @@ -2196,7 +2191,7 @@ int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, c //================================================================================== -static void R_View_UpdateEntityVisible (void) +static void R_View_UpdateEntityVisible (renderscene_t* scene) { int i, renderimask; entity_render_t *ent; @@ -2204,27 +2199,27 @@ static void R_View_UpdateEntityVisible (void) 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; } } } @@ -2232,10 +2227,10 @@ static void R_View_UpdateEntityVisible (void) 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)); } } } @@ -2264,7 +2259,7 @@ int R_DrawBrushModelsSky (void) } 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; @@ -2272,12 +2267,12 @@ static void R_DrawModels(void) 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 @@ -2285,7 +2280,7 @@ static void R_DrawModels(void) } } -static void R_DrawModelsDepth(void) +static void R_DrawModelsDepth(renderscene_t* scene) { int i; entity_render_t *ent; @@ -2293,17 +2288,17 @@ static void R_DrawModelsDepth(void) 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; @@ -2311,17 +2306,17 @@ static void R_DrawModelsDebug(void) 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; @@ -2329,24 +2324,24 @@ static void R_DrawModelsAddWaterPlanes(void) 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; @@ -2410,59 +2405,59 @@ static void R_View_SetFrustum(void) 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, @@ -2494,32 +2489,32 @@ static void R_View_SetFrustum(void) //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); } } @@ -2556,7 +2551,7 @@ void R_ResetViewRendering2D(void) 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) { @@ -2566,11 +2561,11 @@ void R_ResetViewRendering3D(void) 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); @@ -2579,14 +2574,14 @@ void R_ResetViewRendering3D(void) 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); } /* @@ -2650,7 +2645,7 @@ void R_ResetViewRendering3D(void) "#endif // FRAGMENT_SHADER\n" */ -void R_RenderScene(qboolean addwaterplanes); +void R_RenderScene(renderscene_t* scene, qboolean addwaterplanes); static void R_Water_StartFrame(void) { @@ -2772,13 +2767,13 @@ static void R_Water_AddWaterPlane(msurface_t *surface) } } -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++) @@ -2803,72 +2798,72 @@ static void R_Water_ProcessPlanes(void) // 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"); @@ -3125,31 +3120,31 @@ void R_Bloom_MakeTexture(void) } } -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(); @@ -3157,11 +3152,11 @@ void R_HDR_RenderBloomTexture(void) 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) @@ -3232,8 +3227,6 @@ static void R_BlendView(void) } } -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! @@ -3263,88 +3256,88 @@ void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as t } } -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; } /* @@ -3352,9 +3345,9 @@ void R_UpdateVariables(void) 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; @@ -3368,24 +3361,24 @@ void R_RenderView(void) 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) @@ -3402,16 +3395,16 @@ extern void R_DrawPortals (void); 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"); @@ -3426,16 +3419,16 @@ void R_RenderScene(qboolean addwaterplanes) 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) @@ -3445,7 +3438,7 @@ void R_RenderScene(qboolean addwaterplanes) R_SkyStartFrame(); - R_View_Update(); + R_View_Update(scene); if (r_timereport_active) R_TimeReport("visibility"); @@ -3476,7 +3469,7 @@ void R_RenderScene(qboolean addwaterplanes) } if (r_depthfirst.integer >= 2) { - R_DrawModelsDepth(); + R_DrawModelsDepth(scene); if (r_timereport_active) R_TimeReport("modeldepth"); } @@ -3492,7 +3485,7 @@ void R_RenderScene(qboolean addwaterplanes) if (r_refdef.extraupdate) S_ExtraUpdate (); - R_DrawModels(); + R_DrawModels(scene); if (r_timereport_active) R_TimeReport("models"); @@ -3502,9 +3495,9 @@ void R_RenderScene(qboolean addwaterplanes) 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) @@ -3586,7 +3579,7 @@ void R_RenderScene(qboolean addwaterplanes) 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"); } diff --git a/menu.c b/menu.c index 29467965..d7078b4f 100644 --- a/menu.c +++ b/menu.c @@ -5068,11 +5068,16 @@ void MP_KeyEvent (int key, char ascii, qboolean downevent) 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; @@ -5223,4 +5228,7 @@ void MR_Init(void) MR_SetRouting (TRUE); else MR_SetRouting (FALSE); + + // FIXME: needed so cl.max_entities is set + CL_ClearState (); } diff --git a/mvm_cmds.c b/mvm_cmds.c index 11d0ddc9..6dc56533 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "prvm_cmds.h" +#include "clvm_cmds.h" #include "menu.h" //============================================================================ @@ -23,6 +24,7 @@ char *vm_m_extensions = #ifdef SUPPORT_GECKO "DP_GECKO_SUPPORT " #endif +"DP_QC_RENDER_SCENE" ; /* @@ -872,9 +874,9 @@ VM_altstr_ins, // #86 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 @@ -1082,16 +1084,17 @@ NULL, // #296 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 @@ -1421,13 +1424,39 @@ VM_M_getextresponse // #624 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(); } diff --git a/r_shadow.c b/r_shadow.c index c4f98c92..14d671cd 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -3165,7 +3165,7 @@ void R_ShadowVolumeLighting(qboolean visible) 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; @@ -3179,7 +3179,7 @@ void R_DrawModelShadows(void) 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; @@ -3192,9 +3192,9 @@ void R_DrawModelShadows(void) 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)) { @@ -3219,8 +3219,8 @@ void R_DrawModelShadows(void) // 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(); @@ -3234,7 +3234,7 @@ void R_DrawModelShadows(void) 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 diff --git a/render.h b/render.h index 49d3c362..4982b4a4 100644 --- a/render.h +++ b/render.h @@ -121,8 +121,8 @@ extern cvar_t r_wateralpha; 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 -- 2.39.2