#define MAX_LIGHTMAP_SIZE 256
-cvar_t r_ambient = {0, "r_ambient", "0"};
-cvar_t r_drawportals = {0, "r_drawportals", "0"};
-cvar_t r_testvis = {0, "r_testvis", "0"};
-cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
-cvar_t r_drawcollisionbrushes_polygonfactor = {0, "r_drawcollisionbrushes_polygonfactor", "-1"};
-cvar_t r_drawcollisionbrushes_polygonoffset = {0, "r_drawcollisionbrushes_polygonoffset", "0"};
-cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0"};
+cvar_t r_ambient = {0, "r_ambient", "0", "brighter world cheat (not allowed in multiplayer), value is 0-128"};
+cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
+cvar_t r_lockpvs = {0, "r_lockpvs", "0", "disables pvs switching, allows you to walk around and inspect what is visible from a given location in the map (anything not visible from your current location will not be drawn)"};
+cvar_t r_lockvisibility = {0, "r_lockvisibility", "0", "disables visibility updates, allows you to walk around and inspect what is visible from a given viewpoint in the map (anything offscreen at the moment this is enabled will not be drawn)"};
+cvar_t r_useportalculling = {0, "r_useportalculling", "1", "use advanced portal culling visibility method to improve performance over just Potentially Visible Set, provides an even more significant speed improvement in unvised maps"};
+cvar_t r_q3bsp_renderskydepth = {0, "r_q3bsp_renderskydepth", "0", "draws sky depth masking in q3 maps (as in q1 maps), this means for example that sky polygons can hide other things"};
// flag arrays used for visibility checking on world model
// (all other entities have no per-surface/per-leaf visibility checks)
// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_clusters
-qbyte r_pvsbits[(32768+7)>>3];
+unsigned char r_pvsbits[(32768+7)>>3];
// TODO: dynamic resize according to r_refdef.worldmodel->brush.num_leafs
-qbyte r_worldleafvisible[32768];
+unsigned char r_worldleafvisible[32768];
// TODO: dynamic resize according to r_refdef.worldmodel->num_surfaces
-qbyte r_worldsurfacevisible[262144];
+unsigned char r_worldsurfacevisible[262144];
/*
===============
{
int smax, tmax, i, j, size, size3, maps, stride, l;
unsigned int *bl, scale;
- qbyte *lightmap, *out, *stain;
+ unsigned char *lightmap, *out, *stain;
static unsigned int intblocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*3]; // LordHavoc: *3 for colored lighting
- static qbyte templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
+ static unsigned char templight[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE*4];
// update cached lighting info
surface->cached_dlight = 0;
float ndist, a, ratio, maxdist, maxdist2, maxdist3, invradius, sdtable[256], td, dist2;
msurface_t *surface, *endsurface;
int i, s, t, smax, tmax, smax3, impacts, impactt, stained;
- qbyte *bl;
+ unsigned char *bl;
vec3_t impact;
maxdist = radius * radius;
{
if (a > 1)
a = 1;
- bl[0] = (qbyte) ((float) bl[0] + a * ((fcolor[0] + ratio * fcolor[4]) - (float) bl[0]));
- bl[1] = (qbyte) ((float) bl[1] + a * ((fcolor[1] + ratio * fcolor[5]) - (float) bl[1]));
- bl[2] = (qbyte) ((float) bl[2] + a * ((fcolor[2] + ratio * fcolor[6]) - (float) bl[2]));
+ bl[0] = (unsigned char) ((float) bl[0] + a * ((fcolor[0] + ratio * fcolor[4]) - (float) bl[0]));
+ bl[1] = (unsigned char) ((float) bl[1] + a * ((fcolor[1] + ratio * fcolor[5]) - (float) bl[1]));
+ bl[2] = (unsigned char) ((float) bl[2] + a * ((fcolor[2] + ratio * fcolor[6]) - (float) bl[2]));
stained = true;
}
}
R_StainNode(r_refdef.worldmodel->brush.data_nodes + r_refdef.worldmodel->brushq1.hulls[0].firstclipnode, r_refdef.worldmodel, origin, radius, fcolor);
// look for embedded bmodels
- for (n = 0;n < cl_num_brushmodel_entities;n++)
+ for (n = 0;n < cl.num_brushmodel_entities;n++)
{
- ent = &cl_entities[cl_brushmodel_entities[n]].render;
+ ent = &cl.entities[cl.brushmodel_entities[n]].render;
model = ent->model;
if (model && model->name[0] == '*')
{
=============================================================
*/
-static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
+static void R_DrawPortal_Callback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
{
+ const mportal_t *portal = (mportal_t *)ent;
int i;
float *v;
rmeshstate_t m;
- const mportal_t *portal = (mportal_t *)calldata1;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthMask(false);
GL_DepthTest(true);
- R_Mesh_Matrix(&r_identitymatrix);
+ R_Mesh_Matrix(&identitymatrix);
memset(&m, 0, sizeof(m));
m.pointer_vertex = varray_vertex3f;
R_Mesh_State(&m);
- i = calldata2;
+ i = surfacenumber;
GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
((i & 0x0038) >> 3) * (1.0f / 7.0f),
((i & 0x01C0) >> 6) * (1.0f / 7.0f),
// LordHavoc: this is just a nice debugging tool, very slow
static void R_DrawPortals(void)
{
- int i, leafnum;//, portalnum;
+ int i, leafnum;
mportal_t *portal;
float center[3], f;
model_t *model = r_refdef.worldmodel;
VectorAdd(center, portal->points[i].position, center);
f = ixtable[portal->numpoints];
VectorScale(center, f, center);
- //R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum);
- R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, leafnum);
+ R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, (entity_render_t *)portal, leafnum, r_shadow_rtlight);
}
}
}
// if possible find the leaf the view origin is in
viewleaf = model->brush.PointInLeaf ? model->brush.PointInLeaf(model, r_vieworigin) : NULL;
// if possible fetch the visible cluster bits
- if (model->brush.FatPVS)
+ if (!r_lockpvs.integer && model->brush.FatPVS)
model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
- // clear the visible surface and leaf flags arrays
- memset(r_worldsurfacevisible, 0, model->num_surfaces);
- memset(r_worldleafvisible, 0, model->brush.num_leafs);
-
- // if the user prefers surfaceworldnode (testing?) or the viewleaf could
- // not be found, or the viewleaf is not part of the visible world
- // (floating around in the void), use the pvs method
- if (r_surfaceworldnode.integer || !viewleaf || viewleaf->clusterindex < 0)
+ if (!r_lockvisibility.integer)
{
- // pvs method:
- // similar to quake's RecursiveWorldNode but without cache misses
- for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
+ // clear the visible surface and leaf flags arrays
+ memset(r_worldsurfacevisible, 0, model->num_surfaces);
+ memset(r_worldleafvisible, 0, model->brush.num_leafs);
+
+ // if floating around in the void (no pvs data available, and no
+ // portals available), simply use all on-screen leafs.
+ if (!viewleaf || viewleaf->clusterindex < 0)
{
- // if leaf is in current pvs and on the screen, mark its surfaces
- if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
+ // no visibility method: (used when floating around in the void)
+ // simply cull each leaf to the frustum (view pyramid)
+ // similar to quake's RecursiveWorldNode but without cache misses
+ for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
{
- renderstats.world_leafs++;
- r_worldleafvisible[j] = true;
- if (leaf->numleafsurfaces)
- for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
+ // if leaf is in current pvs and on the screen, mark its surfaces
+ if (!R_CullBox(leaf->mins, leaf->maxs))
+ {
+ renderstats.world_leafs++;
+ r_worldleafvisible[j] = true;
+ if (leaf->numleafsurfaces)
+ for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
+ r_worldsurfacevisible[*mark] = true;
+ }
}
}
- }
- else
- {
- int leafstackpos;
- mportal_t *p;
- mleaf_t *leafstack[8192];
- // portal method:
- // follows portals leading outward from viewleaf, does not venture
- // offscreen or into leafs that are not visible, faster than Quake's
- // RecursiveWorldNode and vastly better in unvised maps, often culls a
- // lot of surface that pvs alone would miss
- leafstack[0] = viewleaf;
- leafstackpos = 1;
- while (leafstackpos)
+ // if the user prefers to disable portal culling (testing?), simply
+ // use all on-screen leafs that are in the pvs.
+ else if (!r_useportalculling.integer)
{
- renderstats.world_leafs++;
- leaf = leafstack[--leafstackpos];
- r_worldleafvisible[leaf - model->brush.data_leafs] = true;
- // mark any surfaces bounding this leaf
- if (leaf->numleafsurfaces)
- for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
- // follow portals into other leafs
- // the checks are:
- // if viewer is behind portal (portal faces outward into the scene)
- // and the portal polygon's bounding box is on the screen
- // and the leaf has not been visited yet
- // and the leaf is visible in the pvs
- // (the first two checks won't cause as many cache misses as the leaf checks)
- for (p = leaf->portals;p;p = p->next)
+ // pvs method:
+ // simply check if each leaf is in the Potentially Visible Set,
+ // and cull to frustum (view pyramid)
+ // similar to quake's RecursiveWorldNode but without cache misses
+ for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
{
- renderstats.world_portals++;
- if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !r_worldleafvisible[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex))
- leafstack[leafstackpos++] = p->past;
+ // if leaf is in current pvs and on the screen, mark its surfaces
+ if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
+ {
+ renderstats.world_leafs++;
+ r_worldleafvisible[j] = true;
+ if (leaf->numleafsurfaces)
+ for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
+ r_worldsurfacevisible[*mark] = true;
+ }
+ }
+ }
+ // otherwise use a recursive portal flow, culling each portal to
+ // frustum and checking if the leaf the portal leads to is in the pvs
+ else
+ {
+ int leafstackpos;
+ mportal_t *p;
+ mleaf_t *leafstack[8192];
+ // simple-frustum portal method:
+ // follows portals leading outward from viewleaf, does not venture
+ // offscreen or into leafs that are not visible, faster than
+ // Quake's RecursiveWorldNode and vastly better in unvised maps,
+ // often culls some surfaces that pvs alone would miss
+ // (such as a room in pvs that is hidden behind a wall, but the
+ // passage leading to the room is off-screen)
+ leafstack[0] = viewleaf;
+ leafstackpos = 1;
+ while (leafstackpos)
+ {
+ renderstats.world_leafs++;
+ leaf = leafstack[--leafstackpos];
+ r_worldleafvisible[leaf - model->brush.data_leafs] = true;
+ // mark any surfaces bounding this leaf
+ if (leaf->numleafsurfaces)
+ for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
+ r_worldsurfacevisible[*mark] = true;
+ // follow portals into other leafs
+ // the checks are:
+ // if viewer is behind portal (portal faces outward into the scene)
+ // and the portal polygon's bounding box is on the screen
+ // and the leaf has not been visited yet
+ // and the leaf is visible in the pvs
+ // (the first two checks won't cause as many cache misses as the leaf checks)
+ for (p = leaf->portals;p;p = p->next)
+ {
+ renderstats.world_portals++;
+ if (DotProduct(r_vieworigin, p->plane.normal) < (p->plane.dist + 1) && !R_CullBox(p->mins, p->maxs) && !r_worldleafvisible[p->past - model->brush.data_leafs] && CHECKPVSBIT(r_pvsbits, p->past->clusterindex))
+ leafstack[leafstackpos++] = p->past;
+ }
}
}
}
{
if (ent->model == NULL)
return;
- if (r_drawcollisionbrushes.integer < 2)
- R_DrawSurfaces(ent, true);
+ R_DrawSurfaces(ent, true);
}
void R_Q1BSP_Draw(entity_render_t *ent)
model_t *model = ent->model;
if (model == NULL)
return;
- if (r_drawcollisionbrushes.integer < 2)
- R_DrawSurfaces(ent, false);
- if (r_drawcollisionbrushes.integer >= 1 && model->brush.num_brushes)
+ R_DrawSurfaces(ent, false);
+ if (r_showcollisionbrushes.integer && model->brush.num_brushes && !r_showtrispass)
{
int i;
msurface_t *surface;
R_Mesh_Matrix(&ent->matrix);
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
GL_DepthMask(false);
- GL_DepthTest(true);
- qglPolygonOffset(r_drawcollisionbrushes_polygonfactor.value, r_drawcollisionbrushes_polygonoffset.value);
+ GL_DepthTest(!r_showdisabledepthtest.integer);
+ qglPolygonOffset(r_showcollisionbrushes_polygonfactor.value, r_showcollisionbrushes_polygonoffset.value);
for (i = 0, brush = model->brush.data_brushes + model->firstmodelbrush;i < model->nummodelbrushes;i++, brush++)
if (brush->colbrushf && brush->colbrushf->numtriangles)
R_DrawCollisionBrush(brush->colbrushf);
vec3_t relativelightorigin;
float lightradius;
int *outleaflist;
- qbyte *outleafpvs;
+ unsigned char *outleafpvs;
int outnumleafs;
int *outsurfacelist;
- qbyte *outsurfacepvs;
+ unsigned char *outsurfacepvs;
int outnumsurfaces;
vec3_t outmins;
vec3_t outmaxs;
vec3_t lightmins;
vec3_t lightmaxs;
- const qbyte *pvs;
+ const unsigned char *pvs;
}
r_q1bsp_getlightinfo_t;
R_Q1BSP_RecursiveGetLightInfo(info, node->children[0]);
node = node->children[1];
}
+ else if (sides == 0)
+ return; // ERROR: NAN bounding box!
else
node = node->children[sides - 1];
}
{
msurface_t *surface = info->model->data_surfaces + surfaceindex;
if (BoxesOverlap(info->lightmins, info->lightmaxs, surface->mins, surface->maxs))
- if ((surface->texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT)) == MATERIALFLAG_WALL)
{
int triangleindex, t;
const int *e;
}
}
-void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, qbyte *outleafpvs, int *outnumleafspointer, int *outsurfacelist, qbyte *outsurfacepvs, int *outnumsurfacespointer)
+void R_Q1BSP_GetLightInfo(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, vec3_t outmins, vec3_t outmaxs, int *outleaflist, unsigned char *outleafpvs, int *outnumleafspointer, int *outsurfacelist, unsigned char *outsurfacepvs, int *outnumsurfacespointer)
{
r_q1bsp_getlightinfo_t info;
VectorCopy(relativelightorigin, info.relativelightorigin);
texture = surface->texture;
if ((texture->basematerialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
continue;
- if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ if ((texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) || (ent->flags & RENDER_NOCULLFACE))
continue;
R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, r_shadow_compilingrtlight->cullmins, r_shadow_compilingrtlight->cullmaxs, surface->mins, surface->maxs);
}
extern float *rsurface_svector3f;
extern float *rsurface_tvector3f;
extern float *rsurface_normal3f;
-extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg);
+extern void RSurf_SetVertexPointer(const entity_render_t *ent, const texture_t *texture, const msurface_t *surface, const vec3_t modelorg, qboolean generatenormals, qboolean generatetangents);
void R_Q1BSP_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist, const vec3_t lightmins, const vec3_t lightmaxs)
{
// check the box in modelspace, it was already checked in worldspace
if (!BoxesOverlap(ent->model->normalmins, ent->model->normalmaxs, lightmins, lightmaxs))
return;
- if (r_drawcollisionbrushes.integer >= 2)
- return;
R_UpdateAllTextureInfo(ent);
if (model->brush.shadowmesh)
{
texture = surface->texture->currentframe;
if ((texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
continue;
- if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ if ((texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2)) || (ent->flags & RENDER_NOCULLFACE))
continue;
R_Shadow_MarkVolumeFromBox(surface->num_firstshadowmeshtriangle, surface->num_triangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
}
texture = surface->texture;//R_FetchAliasSkin(ent, surface->groupmesh);
if (texture->currentmaterialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT) || !surface->num_triangles)
continue;
- RSurf_SetVertexPointer(ent, texture, surface, modelorg);
+ RSurf_SetVertexPointer(ent, texture, surface, modelorg, false, false);
// identify lit faces within the bounding box
R_Shadow_PrepareShadowMark(surface->groupmesh->num_triangles);
R_Shadow_MarkVolumeFromBox(surface->num_firsttriangle, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_element3i, relativelightorigin, lightmins, lightmaxs, surface->mins, surface->maxs);
}
}
+static void R_Q1BSP_DrawLight_TransparentCallback(const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
+{
+ msurface_t *surface = ent->model->data_surfaces + surfacenumber;
+ texture_t *texture = surface->texture;
+ R_UpdateTextureInfo(ent, texture);
+ texture = texture->currentframe;
+ R_Shadow_RenderMode_Begin();
+ R_Shadow_RenderMode_ActiveLight((rtlight_t *)rtlight);
+ R_Shadow_RenderMode_Lighting(false, true);
+ R_Shadow_SetupEntityLight(ent);
+ R_Shadow_RenderSurfacesLighting(ent, texture, 1, &surface);
+ R_Shadow_RenderMode_End();
+}
+
+static void R_Q1BSP_DrawLight_TransparentBatch(const entity_render_t *ent, texture_t *texture, int batchnumsurfaces, msurface_t **batchsurfacelist)
+{
+ int batchsurfaceindex;
+ msurface_t *batchsurface;
+ vec3_t tempcenter, center;
+ for (batchsurfaceindex = 0;batchsurfaceindex < batchnumsurfaces;batchsurfaceindex++)
+ {
+ batchsurface = batchsurfacelist[batchsurfaceindex];
+ tempcenter[0] = (batchsurface->mins[0] + batchsurface->maxs[0]) * 0.5f;
+ tempcenter[1] = (batchsurface->mins[1] + batchsurface->maxs[1]) * 0.5f;
+ tempcenter[2] = (batchsurface->mins[2] + batchsurface->maxs[2]) * 0.5f;
+ Matrix4x4_Transform(&ent->matrix, tempcenter, center);
+ R_MeshQueue_AddTransparent(texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_vieworigin : center, R_Q1BSP_DrawLight_TransparentCallback, ent, batchsurface - ent->model->data_surfaces, r_shadow_rtlight);
+ }
+}
+
#define RSURF_MAX_BATCHSURFACES 1024
-void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *lightcolorpants, float *lightcolorshirt, int numsurfaces, const int *surfacelist)
+void R_Q1BSP_DrawLight(entity_render_t *ent, int numsurfaces, const int *surfacelist)
{
model_t *model = ent->model;
msurface_t *surface;
msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES];
vec3_t modelorg;
texture_t *tex;
- rtexture_t *basetexture = NULL;
- rtexture_t *glosstexture = NULL;
- float specularscale = 0;
qboolean skip;
- if (r_drawcollisionbrushes.integer >= 2)
- return;
- if (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt) < 0.0001)
- return;
R_UpdateAllTextureInfo(ent);
Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
tex = NULL;
{
if (batchnumsurfaces > 0)
{
- R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+ if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+ R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+ else
+ R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
batchnumsurfaces = 0;
}
tex = surface->texture;
texture = surface->texture->currentframe;
- // FIXME: transparent surfaces need to be lit later
- skip = (texture->currentmaterialflags & (MATERIALFLAG_WALL | MATERIALFLAG_TRANSPARENT)) != MATERIALFLAG_WALL;
+ skip = (texture->currentmaterialflags & MATERIALFLAG_SKY) != 0;
if (skip)
continue;
- if (texture->textureflags & Q3TEXTUREFLAG_TWOSIDED)
- qglDisable(GL_CULL_FACE);
- else
- qglEnable(GL_CULL_FACE);
- glosstexture = r_texture_black;
- specularscale = 0;
- if (texture->skin.gloss)
- {
- if (r_shadow_gloss.integer >= 1 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
- {
- glosstexture = texture->skin.gloss;
- specularscale = r_shadow_rtlight->specularscale * r_shadow_glossintensity.value;
- }
- }
- else
- {
- if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0 && r_shadow_glossintensity.value > 0 && r_shadow_rtlight->specularscale > 0)
- {
- glosstexture = r_texture_white;
- specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value;
- }
- }
- basetexture = (ent->colormap < 0 && texture->skin.merged) ? texture->skin.merged : texture->skin.base;
- if ((r_shadow_rtlight->ambientscale + r_shadow_rtlight->diffusescale) * (VectorLength2(lightcolorbase) + VectorLength2(lightcolorpants) + VectorLength2(lightcolorshirt)) + specularscale * VectorLength2(lightcolorbase) < (1.0f / 1048576.0f))
- skip = true;
}
if (!skip && surface->num_triangles)
{
if (batchnumsurfaces == RSURF_MAX_BATCHSURFACES)
{
- R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+ if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+ R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+ else
+ R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
batchnumsurfaces = 0;
}
batchsurfacelist[batchnumsurfaces++] = surface;
}
if (batchnumsurfaces > 0)
{
- R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, glosstexture, specularscale, modelorg);
+ if (texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT)
+ R_Q1BSP_DrawLight_TransparentBatch(ent, texture, batchnumsurfaces, batchsurfacelist);
+ else
+ R_Shadow_RenderSurfacesLighting(ent, texture, batchnumsurfaces, batchsurfacelist);
batchnumsurfaces = 0;
}
qglEnable(GL_CULL_FACE);
}
+//Made by [515]
+void R_ReplaceWorldTexture (void)
+{
+ model_t *m;
+ texture_t *t;
+ int i;
+ const char *r, *newt;
+ m = r_refdef.worldmodel;
+
+ if(Cmd_Argc() < 2)
+ {
+ Con_Print("r_replacemaptexture <texname> <newtexname> - replaces texture\n");
+ Con_Print("r_replacemaptexture <texname> - switch back to default texture\n");
+ return;
+ }
+ if(!cl.islocalgame || !cl.worldmodel)
+ {
+ Con_Print("This command works only in singleplayer\n");
+ return;
+ }
+ r = Cmd_Argv(1);
+ newt = Cmd_Argv(2);
+ if(!newt[0])
+ newt = r;
+ for(i=0,t=m->data_textures;i<m->num_textures;i++,t++)
+ {
+ if(t->width && !strcasecmp(t->name, r))
+ {
+ if(Mod_LoadSkinFrame(&t->skin, (char*)newt, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, r_fullbrights.integer))
+ {
+ Con_Printf("%s replaced with %s\n", r, newt);
+ return;
+ }
+ else
+ {
+ Con_Printf("%s was not found\n", newt);
+ Mod_LoadSkinFrame(&t->skin, (char*)r, TEXF_MIPMAP | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, false, r_fullbrights.integer);//back to default
+ return;
+ }
+ }
+ }
+}
+
+//Made by [515]
+void R_ListWorldTextures (void)
+{
+ model_t *m;
+ texture_t *t;
+ int i;
+ m = r_refdef.worldmodel;
+
+ Con_Print("Worldmodel textures :\n");
+ for(i=0,t=m->data_textures;i<m->num_textures;i++,t++)
+ if(t->skin.base != r_texture_notexture)
+ Con_Printf("%s\n", t->name);
+}
+
#if 0
static void gl_surf_start(void)
{
Cvar_RegisterVariable(&r_ambient);
Cvar_RegisterVariable(&r_drawportals);
- Cvar_RegisterVariable(&r_testvis);
- Cvar_RegisterVariable(&r_surfaceworldnode);
- Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
- Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);
+ Cvar_RegisterVariable(&r_lockpvs);
+ Cvar_RegisterVariable(&r_lockvisibility);
+ Cvar_RegisterVariable(&r_useportalculling);
Cvar_RegisterVariable(&r_q3bsp_renderskydepth);
+ Cmd_AddCommand ("r_replacemaptexture", R_ReplaceWorldTexture, "override a map texture for testing purposes"); // By [515]
+ Cmd_AddCommand ("r_listmaptextures", R_ListWorldTextures, "list all textures used by the current map"); // By [515]
+
//R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
}