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_detailtextures = {CVAR_SAVE, "r_detailtextures", "1"};
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"};
model = ent->model;
if (model && model->name[0] == '*')
{
- Mod_CheckLoaded(model);
if (model->brush.data_nodes)
{
Matrix4x4_Transform(&ent->inversematrix, origin, org);
int i;
float *v;
rmeshstate_t m;
- const mportal_t *portal = calldata1;
+ const mportal_t *portal = (mportal_t *)calldata1;
GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL_DepthMask(false);
GL_DepthTest(true);
// 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))
{
- c_leafs++;
+ renderstats.world_leafs++;
r_worldleafvisible[j] = true;
if (leaf->numleafsurfaces)
for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
leafstackpos = 1;
while (leafstackpos)
{
- c_leafs++;
+ renderstats.world_leafs++;
leaf = leafstack[--leafstackpos];
r_worldleafvisible[leaf - model->brush.data_leafs] = true;
// mark any surfaces bounding this leaf
// 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;
+ }
}
}
void R_Q1BSP_Draw(entity_render_t *ent)
{
- if (ent->model == NULL)
+ model_t *model = ent->model;
+ if (model == NULL)
return;
- c_bmodels++;
if (r_drawcollisionbrushes.integer < 2)
R_DrawSurfaces(ent, false);
- if (r_drawcollisionbrushes.integer >= 1 && ent->model->brush.num_brushes)
+ if (r_drawcollisionbrushes.integer >= 1 && model->brush.num_brushes)
{
int i;
- model_t *model = ent->model;
msurface_t *surface;
q3mbrush_t *brush;
R_Mesh_Matrix(&ent->matrix);
*outnumsurfacespointer = info.outnumsurfaces;
}
+void R_Q1BSP_CompileShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius, int numsurfaces, const int *surfacelist)
+{
+ model_t *model = ent->model;
+ msurface_t *surface;
+ int surfacelistindex;
+ float projectdistance = lightradius + model->radius*2 + r_shadow_projectdistance.value;
+ texture_t *texture;
+ r_shadow_compilingrtlight->static_meshchain_shadow = Mod_ShadowMesh_Begin(r_shadow_mempool, 32768, 32768, NULL, NULL, NULL, false, false, true);
+ R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
+ for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
+ {
+ surface = model->data_surfaces + surfacelist[surfacelistindex];
+ texture = surface->texture;
+ if ((texture->basematerialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
+ continue;
+ if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
+ 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);
+ }
+ R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + projectdistance, numshadowmark, shadowmarklist);
+ r_shadow_compilingrtlight->static_meshchain_shadow = Mod_ShadowMesh_Finish(r_shadow_mempool, r_shadow_compilingrtlight->static_meshchain_shadow, false, false);
+}
+
extern float *rsurface_vertex3f;
extern float *rsurface_svector3f;
extern float *rsurface_tvector3f;
return;
if (r_drawcollisionbrushes.integer >= 2)
return;
- if (!r_shadow_compilingrtlight)
- R_UpdateAllTextureInfo(ent);
+ R_UpdateAllTextureInfo(ent);
if (model->brush.shadowmesh)
{
R_Shadow_PrepareShadowMark(model->brush.shadowmesh->numtriangles);
- if (r_shadow_compilingrtlight)
- {
- for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
- {
- surface = model->data_surfaces + surfacelist[surfacelistindex];
- texture = surface->texture;
- if ((texture->basematerialflags & (MATERIALFLAG_NODRAW | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_WALL)) != MATERIALFLAG_WALL)
- continue;
- if (texture->textureflags & (Q3TEXTUREFLAG_TWOSIDED | Q3TEXTUREFLAG_AUTOSPRITE | Q3TEXTUREFLAG_AUTOSPRITE2))
- 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);
- }
- }
- else
+ for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
- for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
- {
- surface = model->data_surfaces + surfacelist[surfacelistindex];
- 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))
- 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);
- }
+ surface = model->data_surfaces + surfacelist[surfacelistindex];
+ 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))
+ 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);
}
R_Shadow_VolumeFromList(model->brush.shadowmesh->numverts, model->brush.shadowmesh->numtriangles, model->brush.shadowmesh->vertex3f, model->brush.shadowmesh->element3i, model->brush.shadowmesh->neighbor3i, relativelightorigin, lightradius + model->radius + projectdistance, numshadowmark, shadowmarklist);
}
}
}
-void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, int numsurfaces, const int *surfacelist)
+#define RSURF_MAX_BATCHSURFACES 1024
+
+void R_Q1BSP_DrawLight(entity_render_t *ent, float *lightcolorbase, float *lightcolorpants, float *lightcolorshirt, int numsurfaces, const int *surfacelist)
{
model_t *model = ent->model;
msurface_t *surface;
texture_t *texture;
- int surfacelistindex;
+ int surfacelistindex, batchnumsurfaces;
+ msurface_t *batchsurfacelist[RSURF_MAX_BATCHSURFACES];
vec3_t modelorg;
texture_t *tex;
- vec3_t lightcolorpants, lightcolorshirt;
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;
texture = NULL;
skip = false;
+ batchnumsurfaces = 0;
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
if ((ent == r_refdef.worldentity && !r_worldsurfacevisible[surfacelist[surfacelistindex]]))
continue;
surface = model->data_surfaces + surfacelist[surfacelistindex];
+ renderstats.lights_lighttriangles += surface->num_triangles;
if (tex != surface->texture)
{
+ 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);
+ batchnumsurfaces = 0;
+ }
tex = surface->texture;
texture = surface->texture->currentframe;
// FIXME: transparent surfaces need to be lit later
specularscale = r_shadow_rtlight->specularscale * r_shadow_gloss2intensity.value;
}
}
- VectorClear(lightcolorpants);
- VectorClear(lightcolorshirt);
- if (ent->colormap >= 0)
- {
- // 128-224 are backwards ranges
- int b = (ent->colormap & 0xF) << 4;b += (b >= 128 && b < 224) ? 4 : 12;
- if (texture->skin.pants && b < 224)
- {
- qbyte *bcolor = (qbyte *) (&palette_complete[b]);
- lightcolorpants[0] = lightcolorbase[0] * bcolor[0] * (1.0f / 255.0f);
- lightcolorpants[1] = lightcolorbase[1] * bcolor[1] * (1.0f / 255.0f);
- lightcolorpants[2] = lightcolorbase[2] * bcolor[2] * (1.0f / 255.0f);
- }
- // 128-224 are backwards ranges
- b = (ent->colormap & 0xF0);b += (b >= 128 && b < 224) ? 4 : 12;
- if (texture->skin.shirt && b < 224)
- {
- qbyte *bcolor = (qbyte *) (&palette_complete[b]);
- lightcolorshirt[0] = lightcolorbase[0] * bcolor[0] * (1.0f / 255.0f);
- lightcolorshirt[1] = lightcolorbase[1] * bcolor[1] * (1.0f / 255.0f);
- lightcolorshirt[2] = lightcolorbase[2] * bcolor[2] * (1.0f / 255.0f);
- }
- basetexture = texture->skin.base;
- }
- else
- basetexture = texture->skin.merged ? texture->skin.merged : texture->skin.base;
+ 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)
- continue;
- RSurf_SetVertexPointer(ent, texture, surface, modelorg);
- if (!rsurface_svector3f)
+ if (!skip && surface->num_triangles)
{
- rsurface_svector3f = varray_svector3f;
- rsurface_tvector3f = varray_tvector3f;
- rsurface_normal3f = varray_normal3f;
- Mod_BuildTextureVectorsAndNormals(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, rsurface_vertex3f, surface->groupmesh->data_texcoordtexture2f, surface->groupmesh->data_element3i + surface->num_firsttriangle * 3, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, r_smoothnormals_areaweighting.integer);
+ 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);
+ batchnumsurfaces = 0;
+ }
+ batchsurfacelist[batchnumsurfaces++] = surface;
}
- R_Shadow_RenderLighting(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (surface->groupmesh->data_element3i + 3 * surface->num_firsttriangle), rsurface_vertex3f, rsurface_svector3f, rsurface_tvector3f, rsurface_normal3f, surface->groupmesh->data_texcoordtexture2f, lightcolorbase, lightcolorpants, lightcolorshirt, basetexture, texture->skin.pants, texture->skin.shirt, texture->skin.nmap, texture->skin.gloss);
+ }
+ 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);
+ batchnumsurfaces = 0;
}
qglEnable(GL_CULL_FACE);
}
Cvar_RegisterVariable(&r_ambient);
Cvar_RegisterVariable(&r_drawportals);
Cvar_RegisterVariable(&r_testvis);
- Cvar_RegisterVariable(&r_detailtextures);
Cvar_RegisterVariable(&r_surfaceworldnode);
Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonfactor);
Cvar_RegisterVariable(&r_drawcollisionbrushes_polygonoffset);