cvar_t r_testvis = {0, "r_testvis", "0"};
cvar_t r_floatbuildlightmap = {0, "r_floatbuildlightmap", "0"};
cvar_t r_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"};
+cvar_t r_surfaceworldnode = {0, "r_surfaceworldnode", "0"};
+cvar_t r_cullsurface = {0, "r_cullsurface", "0"};
static int dlightdivtable[32768];
-static int R_IntAddDynamicLights (msurface_t *surf)
+// variables used by R_PVSUpdate
+int r_pvsframecount = 0;
+mleaf_t *r_viewleaf = NULL;
+int r_viewleafnovis = 0;
+
+static int R_IntAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
{
int sdtable[256], lnum, td, maxdist, maxdist2, maxdist3, i, s, t, smax, tmax, smax3, red, green, blue, lit, dist2, impacts, impactt, subtract;
unsigned int *bl;
if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
continue; // not lit by this light
- softwareuntransform(r_dlight[lnum].origin, local);
+ Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
// for comparisons to minimum acceptable light
return lit;
}
-static int R_FloatAddDynamicLights (msurface_t *surf)
+static int R_FloatAddDynamicLights (const matrix4x4_t *matrix, msurface_t *surf)
{
int lnum, s, t, smax, tmax, smax3, lit, impacts, impactt;
float sdtable[256], *bl, k, dist, dist2, maxdist, maxdist2, maxdist3, td1, td, red, green, blue, impact[3], local[3], subtract;
if (!(surf->dlightbits[lnum >> 5] & (1 << (lnum & 31))))
continue; // not lit by this light
- softwareuntransform(r_dlight[lnum].origin, local);
+ Matrix4x4_Transform(matrix, r_dlight[lnum].origin, local);
dist = DotProduct (local, surf->plane->normal) - surf->plane->dist;
// for comparisons to minimum acceptable light
if (surf->dlightframe == r_framecount && r_dlightmap.integer)
{
- surf->cached_dlight = R_IntAddDynamicLights(surf);
+ surf->cached_dlight = R_IntAddDynamicLights(&ent->inversematrix, surf);
if (surf->cached_dlight)
c_light_polys++;
else if (dlightchanged)
if (surf->dlightframe == r_framecount && r_dlightmap.integer)
{
- surf->cached_dlight = R_FloatAddDynamicLights(surf);
+ surf->cached_dlight = R_FloatAddDynamicLights(&ent->inversematrix, surf);
if (surf->cached_dlight)
c_light_polys++;
else if (dlightchanged)
icolor[7] = ca2;
model = cl.worldmodel;
- R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor);
+ if (model)
+ R_StainNode(model->nodes + model->hulls[0].firstclipnode, model, origin, radius, icolor);
// look for embedded bmodels
for (n = 0;n < cl_num_brushmodel_entities;n++)
{
VectorSubtract(v, modelorg, diff);
f = exp(fogdensity/DotProduct(diff, diff));
- c[0] = r * f;
- c[1] = g * f;
- c[2] = b * f;
- c[3] = a;
+ c[0] = r;
+ c[1] = g;
+ c[2] = b;
+ c[3] = a * f;
}
}
// note: this untransforms lights to do the checking,
// and takes surf->mesh->vertex data
-static int RSurf_LightCheck(const int *dlightbits, surfmesh_t *mesh)
+static int RSurf_LightCheck(const matrix4x4_t *matrix, const int *dlightbits, surfmesh_t *mesh)
{
int i, l;
rdlight_t *rd;
if (dlightbits[l >> 5] & (1 << (l & 31)))
{
rd = &r_dlight[l];
- softwareuntransform(rd->origin, lightorigin);
+ Matrix4x4_Transform(matrix, rd->origin, lightorigin);
for (i = 0, sv = mesh->vertex;i < mesh->numverts;i++, sv++)
if (VectorDistance2(sv->v, lightorigin) < rd->cullradius2)
return true;
if (skyrendernow)
{
skyrendernow = false;
- R_Sky();
+ if (skyrendermasked)
+ R_Sky();
}
// draw depth-only polys
memset(&m, 0, sizeof(m));
- m.blendfunc1 = GL_ZERO;
- m.blendfunc2 = GL_ONE;
+ if (skyrendermasked)
+ {
+ m.blendfunc1 = GL_ZERO;
+ m.blendfunc2 = GL_ONE;
+ }
+ else
+ {
+ // fog sky
+ m.blendfunc1 = GL_ONE;
+ m.blendfunc2 = GL_ZERO;
+ }
m.depthwrite = true;
m.matrix = ent->matrix;
for (surf = firstsurf;surf;surf = surf->chain)
{
memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
- memset(m.color, 0, m.numverts * sizeof(float[4]));
+ if (skyrendermasked)
+ memset(m.color, 0, m.numverts * sizeof(float[4]));
+ else
+ R_FillColors(m.color, m.numverts, fogcolor[0] * m.colorscale, fogcolor[1] * m.colorscale, fogcolor[2] * m.colorscale, 1);
R_Mesh_Render();
}
}
static void RSurfShader_Water(const entity_render_t *ent, const msurface_t *firstsurf)
{
const msurface_t *surf;
+ vec3_t center;
for (surf = firstsurf;surf;surf = surf->chain)
{
if ((r_wateralpha.value < 1 && !(surf->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture)
- R_MeshQueue_AddTransparent(surf->poly_center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+ }
else
R_MeshQueue_Add(RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
}
memset(&m, 0, sizeof(m));
if (ent->effects & EF_ADDITIVE)
{
- m.transparent = true;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE;
}
- else if (surf->currenttexture->fogtexture != NULL || ent->alpha != 1)
+ else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
{
- m.transparent = true;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
}
memset(&m, 0, sizeof(m));
if (ent->effects & EF_ADDITIVE)
{
- m.transparent = true;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE;
}
- else if (surf->currenttexture->fogtexture != NULL || ent->alpha != 1)
+ else if (surf->currenttexture->fogtexture != NULL || ent->alpha < 1)
{
- m.transparent = true;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
}
float modelorg[3];
Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
memset(&m, 0, sizeof(m));
- m.transparent = ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || ent->alpha != 1;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE;
m.tex[0] = R_GetTexture(surf->currenttexture->glowtexture);
float modelorg[3];
Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
memset(&m, 0, sizeof(m));
- m.transparent = ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || ent->alpha != 1;
m.blendfunc1 = GL_SRC_ALPHA;
m.blendfunc2 = GL_ONE;
m.matrix = ent->matrix;
m.matrix = ent->matrix;
for (mesh = surf->mesh;mesh;mesh = mesh->chain)
{
- if (RSurf_LightCheck(surf->dlightbits, mesh))
+ if (RSurf_LightCheck(&ent->inversematrix, surf->dlightbits, mesh))
{
m.numtriangles = mesh->numtriangles;
m.numverts = mesh->numverts;
memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
RSurf_CopyXYZ(mesh->vertex, m.vertex, m.numverts);
R_FillColors(m.color, m.numverts, m.colorscale, m.colorscale, m.colorscale, 1);
- RSurf_CopyAB(mesh->vertex, m.texcoords[0], m.numverts);
+ RSurf_CopyST(mesh->vertex, m.texcoords[0], m.numverts);
R_Mesh_Render();
}
}
}
+static void RSurfShader_Wall_Fullbright_Callback(const void *calldata1, int calldata2)
+{
+ const entity_render_t *ent = calldata1;
+ const msurface_t *surf = ent->model->surfaces + calldata2;
+ RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
+ if (surf->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
+ if (fogenabled)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
+}
+
static void RSurfShader_Wall_Fullbright(const entity_render_t *ent, const msurface_t *firstsurf)
{
const msurface_t *surf;
- for (surf = firstsurf;surf;surf = surf->chain)
+ vec3_t center;
+ if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
{
- c_brush_polys++;
- RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
+ for (surf = firstsurf;surf;surf = surf->chain)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
+ }
}
- for (surf = firstsurf;surf;surf = surf->chain)
- if (surf->currenttexture->glowtexture)
- RSurfShader_Wall_Pass_Glow(ent, surf);
- if (fogenabled)
+ else
+ {
+ for (surf = firstsurf;surf;surf = surf->chain)
+ {
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Fullbright_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_Wall_Pass_BaseFullbright(ent, surf);
+ }
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_Wall_Pass_Fog(ent, surf);
+ if (surf->currenttexture->glowtexture)
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
+ if (fogenabled)
+ for (surf = firstsurf;surf;surf = surf->chain)
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
+ }
+}
+
+static void RSurfShader_Wall_Vertex_Callback(const void *calldata1, int calldata2)
+{
+ const entity_render_t *ent = calldata1;
+ const msurface_t *surf = ent->model->surfaces + calldata2;
+ RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ if (surf->currenttexture->glowtexture)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
+ if (fogenabled)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
}
static void RSurfShader_Wall_Vertex(const entity_render_t *ent, const msurface_t *firstsurf)
{
const msurface_t *surf;
- for (surf = firstsurf;surf;surf = surf->chain)
+ vec3_t center;
+ if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
{
- c_brush_polys++;
- RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ for (surf = firstsurf;surf;surf = surf->chain)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
}
- for (surf = firstsurf;surf;surf = surf->chain)
- if (surf->currenttexture->glowtexture)
- RSurfShader_Wall_Pass_Glow(ent, surf);
- if (fogenabled)
+ else
+ {
+ for (surf = firstsurf;surf;surf = surf->chain)
+ {
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ }
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_Wall_Pass_Fog(ent, surf);
+ if (surf->currenttexture->glowtexture)
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
+ if (fogenabled)
+ for (surf = firstsurf;surf;surf = surf->chain)
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
+ }
}
static void RSurfShader_Wall_Lightmap(const entity_render_t *ent, const msurface_t *firstsurf)
{
const msurface_t *surf;
- if (r_vertexsurfaces.integer || firstsurf->currenttexture->fogtexture != NULL || ent->alpha != 1 || ent->effects & EF_ADDITIVE)
+ vec3_t center;
+ if (ent->alpha < 1 || ent->effects & EF_ADDITIVE)
+ {
+ for (surf = firstsurf;surf;surf = surf->chain)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ }
+ else if (r_vertexsurfaces.integer || ent->alpha < 1 || ent->effects & EF_ADDITIVE)
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
- RSurfShader_Wall_Pass_BaseVertex(ent, surf);
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_Wall_Pass_BaseVertex(ent, surf);
}
for (surf = firstsurf;surf;surf = surf->chain)
if (surf->currenttexture->glowtexture)
- RSurfShader_Wall_Pass_Glow(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Glow(ent, surf);
if (fogenabled)
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_Wall_Pass_Fog(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_Wall_Pass_Fog(ent, surf);
}
else
{
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
- RSurfShader_OpaqueWall_Pass_TripleTexCombine(ent, surf);
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_OpaqueWall_Pass_TripleTexCombine(ent, surf);
}
}
else
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
- RSurfShader_OpaqueWall_Pass_BaseMTex(ent, surf);
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_OpaqueWall_Pass_BaseMTex(ent, surf);
}
if (r_detailtextures.integer)
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
}
}
else
{
for (surf = firstsurf;surf;surf = surf->chain)
{
- c_brush_polys++;
- RSurfShader_OpaqueWall_Pass_BaseTexture(ent, surf);
+ if (surf->currenttexture->fogtexture != NULL)
+ {
+ Matrix4x4_Transform(&ent->matrix, surf->poly_center, center);
+ R_MeshQueue_AddTransparent(center, RSurfShader_Wall_Vertex_Callback, ent, surf - ent->model->surfaces);
+ }
+ else
+ RSurfShader_OpaqueWall_Pass_BaseTexture(ent, surf);
}
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_BaseLightmap(ent, surf);
if (r_detailtextures.integer)
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_BaseDetail(ent, surf);
}
if (!r_dlightmap.integer)
for (surf = firstsurf;surf;surf = surf->chain)
if (surf->dlightframe == r_framecount)
- RSurfShader_OpaqueWall_Pass_Light(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_Light(ent, surf);
for (surf = firstsurf;surf;surf = surf->chain)
if (surf->currenttexture->glowtexture)
- RSurfShader_OpaqueWall_Pass_Glow(ent, surf);
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_Glow(ent, surf);
if (fogenabled)
for (surf = firstsurf;surf;surf = surf->chain)
- RSurfShader_OpaqueWall_Pass_Fog(ent, surf);
- }
-}
-
-/*
-=============================================================
-
- WORLD MODEL
-
-=============================================================
-*/
-
-static void R_SolidWorldNode (entity_render_t *ent)
-{
- if (r_viewleaf->contents != CONTENTS_SOLID)
- {
- int portalstack;
- mportal_t *p, *pstack[8192];
- msurface_t *surf, **mark, **endmark;
- mleaf_t *leaf;
- // LordHavoc: portal-passage worldnode; follows portals leading
- // outward from viewleaf, if a portal leads offscreen it is not
- // followed, in indoor maps this can often cull a great deal of
- // geometry away when pvs data is not present (useful with pvs as well)
-
- leaf = r_viewleaf;
- leaf->worldnodeframe = r_framecount;
- portalstack = 0;
- loc0:
- c_leafs++;
-
- leaf->visframe = r_framecount;
-
- if (leaf->nummarksurfaces)
- {
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
- }
- while (mark < endmark);
- }
-
- // follow portals into other leafs
- p = leaf->portals;
- for (;p;p = p->next)
- {
- if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
- {
- leaf = p->past;
- if (leaf->worldnodeframe != r_framecount)
- {
- leaf->worldnodeframe = r_framecount;
- if (leaf->contents != CONTENTS_SOLID)
- {
- if (R_NotCulledBox(leaf->mins, leaf->maxs))
- {
- p->visframe = r_framecount;
- pstack[portalstack++] = p;
- goto loc0;
-
- loc1:
- p = pstack[--portalstack];
- }
- }
- }
- }
- }
-
- if (portalstack)
- goto loc1;
- }
- else
- {
- mnode_t *nodestack[8192], *node = cl.worldmodel->nodes;
- int nodestackpos = 0;
- // LordHavoc: recursive descending worldnode; if portals are not
- // available, this is a good last resort, can cull large amounts of
- // geometry, but is more time consuming than portal-passage and renders
- // things behind walls
-
-loc2:
- if (R_NotCulledBox(node->mins, node->maxs))
- {
- if (node->numsurfaces)
- {
- msurface_t *surf = cl.worldmodel->surfaces + node->firstsurface, *surfend = surf + node->numsurfaces;
- if (PlaneDiff (r_origin, node->plane) < 0)
- {
- for (;surf < surfend;surf++)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- }
- else
- {
- for (;surf < surfend;surf++)
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
- }
- }
-
- // recurse down the children
- if (node->children[0]->contents >= 0)
- {
- if (node->children[1]->contents >= 0)
- {
- if (nodestackpos < 8192)
- nodestack[nodestackpos++] = node->children[1];
- node = node->children[0];
- goto loc2;
- }
- else
- ((mleaf_t *)node->children[1])->visframe = r_framecount;
- node = node->children[0];
- goto loc2;
- }
- else
- {
- ((mleaf_t *)node->children[0])->visframe = r_framecount;
- if (node->children[1]->contents >= 0)
- {
- node = node->children[1];
- goto loc2;
- }
- else if (nodestackpos > 0)
- {
- ((mleaf_t *)node->children[1])->visframe = r_framecount;
- node = nodestack[--nodestackpos];
- goto loc2;
- }
- }
- }
- else if (nodestackpos > 0)
- {
- node = nodestack[--nodestackpos];
- goto loc2;
- }
+ if (surf->currenttexture->fogtexture == NULL)
+ RSurfShader_OpaqueWall_Pass_Fog(ent, surf);
}
}
-static int r_portalframecount = 0;
-
-static void R_PVSWorldNode()
-{
- int portalstack, i;
- mportal_t *p, *pstack[8192];
- msurface_t *surf, **mark, **endmark;
- mleaf_t *leaf;
- qbyte *worldvis;
-
- worldvis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
-
- leaf = r_viewleaf;
- leaf->worldnodeframe = r_framecount;
- portalstack = 0;
-loc0:
- c_leafs++;
-
- leaf->visframe = r_framecount;
-
- if (leaf->nummarksurfaces)
- {
- mark = leaf->firstmarksurface;
- endmark = mark + leaf->nummarksurfaces;
- do
- {
- surf = *mark++;
- // make sure surfaces are only processed once
- if (surf->worldnodeframe == r_framecount)
- continue;
- surf->worldnodeframe = r_framecount;
- if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
- {
- if (surf->flags & SURF_PLANEBACK)
- surf->visframe = r_framecount;
- }
- else
- {
- if (!(surf->flags & SURF_PLANEBACK))
- surf->visframe = r_framecount;
- }
- }
- while (mark < endmark);
- }
-
- // follow portals into other leafs
- for (p = leaf->portals;p;p = p->next)
- {
- if (DotProduct(r_origin, p->plane.normal) < p->plane.dist)
- {
- leaf = p->past;
- if (leaf->worldnodeframe != r_framecount)
- {
- leaf->worldnodeframe = r_framecount;
- if (leaf->contents != CONTENTS_SOLID)
- {
- i = (leaf - cl.worldmodel->leafs) - 1;
- if (worldvis[i>>3] & (1<<(i&7)))
- {
- if (R_NotCulledBox(leaf->mins, leaf->maxs))
- {
- pstack[portalstack++] = p;
- goto loc0;
-
-loc1:
- p = pstack[--portalstack];
- }
- }
- }
- }
- }
- }
-
- if (portalstack)
- goto loc1;
-}
-
Cshader_t Cshader_wall_vertex = {{NULL, RSurfShader_Wall_Vertex}, NULL};
Cshader_t Cshader_wall_lightmap = {{NULL, RSurfShader_Wall_Lightmap}, NULL};
Cshader_t Cshader_wall_fullbright = {{NULL, RSurfShader_Wall_Fullbright}, NULL};
texture_t *t;
model_t *model;
msurface_t *surf;
+ vec3_t modelorg;
for (i = 0;i < Cshader_count;i++)
Cshaders[i]->chain = NULL;
alttextures = ent->frame != 0;
texframe = (int)(cl.time * 5.0f);
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
for (i = 0;i < model->nummodelsurfaces;i++)
{
surf = model->modelsortedsurfaces[i];
if (surf->visframe == r_framecount)
{
- if (surf->insertframe != r_framecount)
+ // mark any backface surfaces as not visible
+ if (PlaneDist(modelorg, surf->plane) < surf->plane->dist)
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ surf->visframe = -1;
+ }
+ else
+ {
+ if (surf->flags & SURF_PLANEBACK)
+ surf->visframe = -1;
+ }
+ if (surf->visframe == r_framecount)
{
- surf->insertframe = r_framecount;
c_faces++;
t = surf->texinfo->texture;
if (t->animated)
}
else
surf->currenttexture = t;
- }
- surf->chain = surf->shader->chain;
- surf->shader->chain = surf;
+ surf->chain = surf->shader->chain;
+ surf->shader->chain = surf;
+ }
}
}
}
void R_DrawSurfaces (entity_render_t *ent, int type)
{
- int i;
- Cshader_t *shader;
+ int i;
+ Cshader_t *shader;
for (i = 0;i < Cshader_count;i++)
{
}
}
-void R_DrawPortals(entity_render_t *ent)
+static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
{
- int drawportals, i;
+ int i;
float *v;
- mportal_t *portal, *endportal;
rmeshbufferinfo_t m;
- drawportals = r_drawportals.integer;
+ const entity_render_t *ent = calldata1;
+ const mportal_t *portal = ent->model->portals + calldata2;
+ memset(&m, 0, sizeof(m));
+ m.blendfunc1 = GL_SRC_ALPHA;
+ m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
+ m.numverts = portal->numpoints;
+ m.numtriangles = portal->numpoints - 2;
+ m.matrix = ent->matrix;
+ if (R_Mesh_Draw_GetBuffer(&m, false))
+ {
+ for (i = 0;i < m.numtriangles;i++)
+ {
+ m.index[i * 3 + 0] = 0;
+ m.index[i * 3 + 1] = i + 1;
+ m.index[i * 3 + 2] = i + 2;
+ }
+ i = portal - ent->model->portals;
+ R_FillColors(m.color, m.numverts,
+ ((i & 0x0007) >> 0) * (1.0f / 7.0f) * m.colorscale,
+ ((i & 0x0038) >> 3) * (1.0f / 7.0f) * m.colorscale,
+ ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * m.colorscale,
+ 0.125f);
+ if (PlaneDiff(r_origin, (&portal->plane)) > 0)
+ {
+ for (i = portal->numpoints - 1, v = m.vertex;i >= 0;i--, v += 4)
+ VectorCopy(portal->points[i].position, v);
+ }
+ else
+ for (i = 0, v = m.vertex;i < portal->numpoints;i++, v += 4)
+ VectorCopy(portal->points[i].position, v);
+ R_Mesh_Render();
+ }
+}
+
+void R_DrawPortals(entity_render_t *ent)
+{
+ int i;
+ mportal_t *portal, *endportal;
+ float temp[3], center[3], f;
- if (drawportals < 1)
+ if (r_drawportals.integer < 1)
return;
- for (portal = cl.worldmodel->portals, endportal = portal + cl.worldmodel->numportals;portal < endportal;portal++)
+ for (portal = ent->model->portals, endportal = portal + ent->model->numportals;portal < endportal;portal++)
{
- if (portal->visframe == r_portalframecount)
+ if (portal->here->visframe == r_framecount || portal->past->visframe == r_framecount)
{
- memset(&m, 0, sizeof(m));
- m.transparent = true;
- m.blendfunc1 = GL_SRC_ALPHA;
- m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
- m.numverts = portal->numpoints;
- m.numtriangles = portal->numpoints - 2;
- Matrix4x4_CreateIdentity(&m.matrix);
- if (R_Mesh_Draw_GetBuffer(&m, false))
- {
- for (i = 0;i < m.numtriangles;i++)
- {
- m.index[i * 3 + 0] = 0;
- m.index[i * 3 + 1] = i + 1;
- m.index[i * 3 + 2] = i + 2;
- }
- i = portal - cl.worldmodel->portals;
- R_FillColors(m.color, m.numverts,
- ((i & 0x0007) >> 0) * (1.0f / 7.0f) * m.colorscale,
- ((i & 0x0038) >> 3) * (1.0f / 7.0f) * m.colorscale,
- ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * m.colorscale,
- 0.125f);
- if (PlaneDiff(r_origin, (&portal->plane)) > 0)
- {
- for (i = portal->numpoints - 1, v = m.vertex;i >= 0;i--, v += 4)
- VectorCopy(portal->points[i].position, v);
- }
- else
- for (i = 0, v = m.vertex;i < portal->numpoints;i++, v += 4)
- VectorCopy(portal->points[i].position, v);
- R_Mesh_Render();
- }
+ VectorClear(temp);
+ for (i = 0;i < portal->numpoints;i++)
+ VectorAdd(temp, portal->points[i].position, temp);
+ f = ixtable[portal->numpoints];
+ VectorScale(temp, f, temp);
+ Matrix4x4_Transform(&ent->matrix, temp, center);
+ R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, ent, portal - ent->model->portals);
}
}
}
-void R_SetupForBModelRendering(entity_render_t *ent)
+void R_SetupForBrushModelRendering(entity_render_t *ent)
{
- int i;
- msurface_t *surf;
- model_t *model;
- vec3_t modelorg;
+ int i;
+ msurface_t *surf;
+ model_t *model;
+ vec3_t modelorg;
// because bmodels can be reused, we have to decide which things to render
// from scratch every time
-
model = ent->model;
-
Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
for (i = 0;i < model->nummodelsurfaces;i++)
{
- surf = model->modelsortedsurfaces[i];
- if (((surf->flags & SURF_PLANEBACK) == 0) == (PlaneDiff(modelorg, surf->plane) >= 0))
- surf->visframe = r_framecount;
- else
- surf->visframe = -1;
+ surf = model->surfaces + model->firstmodelsurface + i;
+ surf->visframe = r_framecount;
+ surf->pvsframe = -1;
surf->worldnodeframe = -1;
surf->lightframe = -1;
surf->dlightframe = -1;
- surf->insertframe = -1;
}
+ R_PrepareSurfaces(ent);
}
-void R_SetupForWorldRendering(entity_render_t *ent)
+void R_SurfMarkLights (entity_render_t *ent)
{
- // there is only one instance of the world, but it can be rendered in
- // multiple stages
-}
+ int i;
+ msurface_t *surf;
-static void R_SurfMarkLights (entity_render_t *ent)
-{
- int i;
- msurface_t *surf;
+ if (!ent->model)
+ return;
if (r_dynamic.integer)
R_MarkLights(ent);
if (!r_vertexsurfaces.integer)
{
- for (i = 0;i < ent->model->nummodelsurfaces;i++)
+ for (i = 0, surf = ent->model->surfaces + ent->model->firstmodelsurface;i < ent->model->nummodelsurfaces;i++, surf++)
{
- surf = ent->model->modelsortedsurfaces[i];
if (surf->visframe == r_framecount && surf->lightmaptexture != NULL)
{
if (surf->cached_dlight
}
}
-void R_MarkWorldLights(entity_render_t *ent)
+void R_SurfaceWorldNode (entity_render_t *ent)
{
- R_SetupForWorldRendering(ent);
- R_SurfMarkLights(ent);
+ int i;
+ msurface_t *surf;
+ model_t *model;
+ model = ent->model;
+ // FIXME: R_NotCulledBox is absolute, should be done relative
+ for (i = 0, surf = model->surfaces + model->firstmodelsurface;i < model->nummodelsurfaces;i++, surf++)
+ if (surf->pvsframe == r_pvsframecount && (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs)))
+ surf->visframe = r_framecount;
+}
+
+/*
+static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
+{
+ int portalstack, i;
+ mportal_t *p, *pstack[8192];
+ msurface_t *surf, **mark, **endmark;
+ mleaf_t *leaf;
+ // LordHavoc: portal-passage worldnode with PVS;
+ // follows portals leading outward from viewleaf, does not venture
+ // offscreen or into leafs that are not visible, faster than Quake's
+ // RecursiveWorldNode
+ leaf = viewleaf;
+ leaf->worldnodeframe = r_framecount;
+ portalstack = 0;
+loc0:
+ c_leafs++;
+ if (leaf->nummarksurfaces)
+ {
+ for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+ {
+ surf = *mark++;
+ // make sure surfaces are only processed once
+ if (surf->worldnodeframe != r_framecount)
+ {
+ surf->worldnodeframe = r_framecount;
+ if (PlaneDist(r_origin, surf->plane) < surf->plane->dist)
+ {
+ if (surf->flags & SURF_PLANEBACK)
+ surf->visframe = r_framecount;
+ }
+ else
+ {
+ if (!(surf->flags & SURF_PLANEBACK))
+ surf->visframe = r_framecount;
+ }
+ }
+ }
+ }
+ // follow portals into other leafs
+ for (p = leaf->portals;p;p = p->next)
+ {
+ leaf = p->past;
+ if (leaf->worldnodeframe != r_framecount)
+ {
+ leaf->worldnodeframe = r_framecount;
+ // FIXME: R_NotCulledBox is absolute, should be done relative
+ if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+ {
+ p->visframe = r_framecount;
+ pstack[portalstack++] = p;
+ goto loc0;
+loc1:
+ p = pstack[--portalstack];
+ }
+ }
+ }
+ if (portalstack)
+ goto loc1;
+}
+*/
+
+static void R_PortalWorldNode(entity_render_t *ent, mleaf_t *viewleaf)
+{
+ int c, leafstackpos;
+ mleaf_t *leaf, *leafstack[8192];
+ mportal_t *p;
+ msurface_t *surf, **mark;
+ vec3_t modelorg;
+ // LordHavoc: portal-passage worldnode with PVS;
+ // follows portals leading outward from viewleaf, does not venture
+ // offscreen or into leafs that are not visible, faster than Quake's
+ // RecursiveWorldNode
+ Matrix4x4_Transform(&ent->inversematrix, r_origin, modelorg);
+ viewleaf->worldnodeframe = r_framecount;
+ leafstack[0] = viewleaf;
+ leafstackpos = 1;
+ while (leafstackpos)
+ {
+ c_leafs++;
+ leaf = leafstack[--leafstackpos];
+ // only useful for drawing portals
+ //leaf->visframe = r_framecount;
+ // draw any surfaces bounding this leaf
+ if (leaf->nummarksurfaces)
+ {
+ for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+ {
+ surf = *mark++;
+ if (!r_cullsurface.integer || R_NotCulledBox (surf->poly_mins, surf->poly_maxs))
+ surf->visframe = r_framecount;
+ }
+ }
+ // follow portals into other leafs
+ for (p = leaf->portals;p;p = p->next)
+ {
+ leaf = p->past;
+ if (leaf->worldnodeframe != r_framecount)
+ {
+ leaf->worldnodeframe = r_framecount;
+ // FIXME: R_NotCulledBox is absolute, should be done relative
+ if (leaf->pvsframe == r_pvsframecount && R_NotCulledBox(leaf->mins, leaf->maxs))
+ leafstack[leafstackpos++] = leaf;
+ }
+ }
+ }
+}
+
+
+void R_PVSUpdate (mleaf_t *viewleaf)
+{
+ int i, j, l, c, bits;
+ mnode_t *node;
+ mleaf_t *leaf;
+ qbyte *vis;
+ msurface_t **mark;
+
+ if (r_viewleaf == viewleaf && r_viewleafnovis == r_novis.integer)
+ return;
+
+ r_pvsframecount++;
+ r_viewleaf = viewleaf;
+ r_viewleafnovis = r_novis.integer;
+
+ if (viewleaf)
+ {
+ vis = Mod_LeafPVS (viewleaf, cl.worldmodel);
+ for (j = 0;j < cl.worldmodel->numleafs;j += 8)
+ {
+ bits = *vis++;
+ if (bits)
+ {
+ l = cl.worldmodel->numleafs - j;
+ if (l > 8)
+ l = 8;
+ for (i = 0;i < l;i++)
+ {
+ if (bits & (1 << i))
+ {
+ leaf = &cl.worldmodel->leafs[j + i + 1];
+ // mark surfaces bounding this leaf as visible
+ for (c = leaf->nummarksurfaces, mark = leaf->firstmarksurface;c;c--)
+ (*mark++)->pvsframe = r_pvsframecount;
+ // mark parents as visible until we hit an already
+ // marked parent (which is usually very soon)
+ for (node = (mnode_t *)leaf;node && node->pvsframe != r_pvsframecount;node = node->parent)
+ node->pvsframe = r_pvsframecount;
+ }
+ }
+ }
+ }
+ }
}
/*
*/
void R_DrawWorld (entity_render_t *ent)
{
- R_SetupForWorldRendering(ent);
-
- if (r_viewleaf->contents == CONTENTS_SOLID || r_novis.integer || r_viewleaf->compressed_vis == NULL)
- R_SolidWorldNode (ent);
+ // there is only one instance of the world, but it can be rendered in
+ // multiple stages
+ mleaf_t *viewleaf;
+ viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
+ R_PVSUpdate(viewleaf);
+ if (!viewleaf)
+ return;
+ if (r_surfaceworldnode.integer || viewleaf->contents == CONTENTS_SOLID)
+ R_SurfaceWorldNode (ent);
else
- R_PVSWorldNode (ent);
+ R_PortalWorldNode (ent, viewleaf);
}
/*
*/
void R_DrawBrushModelSky (entity_render_t *ent)
{
- R_SetupForBModelRendering(ent);
-
- R_PrepareSurfaces(ent);
+ R_SetupForBrushModelRendering(ent);
R_DrawSurfaces(ent, SHADERSTAGE_SKY);
}
void R_DrawBrushModelNormal (entity_render_t *ent)
{
c_bmodels++;
-
// have to flush queue because of possible lightmap reuse
R_Mesh_Render();
-
- R_SetupForBModelRendering(ent);
-
+ R_SetupForBrushModelRendering(ent);
R_SurfMarkLights(ent);
-
- R_PrepareSurfaces(ent);
-
- if (!skyrendermasked)
- R_DrawSurfaces(ent, SHADERSTAGE_SKY);
R_DrawSurfaces(ent, SHADERSTAGE_NORMAL);
}
static void gl_surf_newmap(void)
{
+ // reset pvs visibility variables so it will update on first frame
+ r_pvsframecount = 1;
+ r_viewleaf = NULL;
+ r_viewleafnovis = false;
}
void GL_Surf_Init(void)
Cvar_RegisterVariable(&r_testvis);
Cvar_RegisterVariable(&r_floatbuildlightmap);
Cvar_RegisterVariable(&r_detailtextures);
+ Cvar_RegisterVariable(&r_surfaceworldnode);
+ Cvar_RegisterVariable(&r_cullsurface);
R_RegisterModule("GL_Surf", gl_surf_start, gl_surf_shutdown, gl_surf_newmap);
}